Refactor domain models (DomFunktionaer, DomReiter, DomPferd) to align with ZNS conventions: simplify naming, update properties, and enhance parser logic. Adjust related controllers, repository methods, and tests. Update MASTER_ROADMAP with changes to domain models.
This commit is contained in:
@@ -40,6 +40,19 @@ Versionierung folgt [Semantic Versioning](https://semver.org/lang/de/).
|
||||
|
||||
---
|
||||
|
||||
## [1.0.1-SNAPSHOT] — 2026-04-05
|
||||
|
||||
### Geändert
|
||||
- **Refactoring:** `DomVerein` zu `Verein`, `DomReiter` zu `Reiter`, `DomPferd` zu `Pferd` und `DomFunktionaer` zu `Funktionaer` umbenannt (Domain, Infrastructure, API, Core).
|
||||
- **Domain:** `personId` ist nun optional (`nullable`) bei `Verein`, `Reiter`, `Pferd` und `Funktionaer`, um ZNS-Initialimporte zu unterstützen.
|
||||
- **Infrastructure:** `VereinTable`, `ReiterTable`, `HorseTable` und `FunktionaerTable` synchronisiert; `personId` ist nun optional.
|
||||
- **API:** `VereinController`, `ReiterController`, `HorseController` und `FunktionaerController` (DTOs/Requests) an die neuen Modelle angepasst.
|
||||
- **Doku:** `Ubiquitous_Language.md` und `MASTER_ROADMAP.md` an das neue Namensschema (`Reiter`, `Pferd`, `Funktionaer`) angepasst.
|
||||
|
||||
### Behoben
|
||||
- **ZNS-Import:** Kompatibilitätsprobleme in `ZnsLegacyParsers` und `ZnsImportService` nach Domain-Refactorings behoben (UUID-Person-Referenzen und Enum-Synchronisation).
|
||||
- **Domain:** Felder `kurzname` und `oepsRegionNummer` bei `Verein` entfernt (nicht in VEREIN01.DAT vorhanden).
|
||||
|
||||
## [1.0.0-SNAPSHOT] — 2026-04-03
|
||||
|
||||
### Hinzugefügt
|
||||
|
||||
+20
-18
@@ -19,10 +19,10 @@ import java.util.zip.ZipInputStream
|
||||
* Domänenobjekte über die jeweiligen Repositories (Upsert-Logik).
|
||||
*
|
||||
* Die Verarbeitungsreihenfolge ist fix:
|
||||
* 1. VEREIN01.DAT → DomVerein (via VereinRepository)
|
||||
* 2. LIZENZ01.DAT → DomReiter (via ReiterRepository)
|
||||
* 3. PFERDE01.DAT → DomPferd (via HorseRepository)
|
||||
* 4. RICHT01.DAT → DomFunktionaer (via FunktionaerRepository)
|
||||
* 1. VEREIN01.DAT → Verein (via VereinRepository)
|
||||
* 2. LIZENZ01.DAT → Reiter (via ReiterRepository)
|
||||
* 3. PFERDE01.DAT → Pferd (via HorseRepository)
|
||||
* 4. RICHT01.DAT → Funktionaer (via FunktionaerRepository)
|
||||
*
|
||||
* Dieser Service hat **keine** Spring-Abhängigkeit und kann daher sowohl
|
||||
* im Backend (REST-Upload) als auch in der Compose Desktop App (Offline-Import)
|
||||
@@ -57,18 +57,19 @@ class ZnsImportService(
|
||||
ZipInputStream(zipInputStream).use { zip ->
|
||||
var entry = zip.nextEntry
|
||||
while (entry != null) {
|
||||
val entryPath = entry.name.uppercase()
|
||||
val fileName = entryPath.substringAfterLast("/")
|
||||
val fileName = entry.name.uppercase().substringAfterLast("/")
|
||||
|
||||
if (fileName in setOf(FILE_VEREIN, FILE_LIZENZ, FILE_PFERDE, FILE_RICHT)) {
|
||||
// Read all bytes from the current entry
|
||||
val bytes = zip.readBytes()
|
||||
// Convert to string using the correct charset and split into lines
|
||||
val content = bytes.toString(CP850)
|
||||
val outputStream = java.io.ByteArrayOutputStream()
|
||||
val buffer = ByteArray(4096)
|
||||
var len: Int
|
||||
while (zip.read(buffer).also { len = it } > 0) {
|
||||
outputStream.write(buffer, 0, len)
|
||||
}
|
||||
val content = outputStream.toString(CP850)
|
||||
val lines = content.split(Regex("\\r?\\n|\\r")).filter { it.isNotBlank() }
|
||||
dateien[fileName] = lines
|
||||
}
|
||||
zip.closeEntry()
|
||||
entry = zip.nextEntry
|
||||
}
|
||||
}
|
||||
@@ -83,6 +84,8 @@ class ZnsImportService(
|
||||
*/
|
||||
suspend fun importiereZip(zipInputStream: InputStream): ZnsImportResult {
|
||||
val dateien = extrahiereDateien(zipInputStream)
|
||||
// println("[DEBUG_LOG] Gefundene Dateien: ${dateien.keys}")
|
||||
// dateien.forEach { (name, lines) -> println("[DEBUG_LOG] Datei $name hat ${lines.size} Zeilen") }
|
||||
|
||||
val fehler = mutableListOf<String>()
|
||||
val warnungen = mutableListOf<String>()
|
||||
@@ -126,13 +129,11 @@ class ZnsImportService(
|
||||
} else {
|
||||
vereinRepository.save(
|
||||
vorhanden.copy(
|
||||
name = verein.name,
|
||||
kurzname = verein.kurzname,
|
||||
vereinName = verein.vereinName,
|
||||
bundesland = verein.bundesland,
|
||||
ort = verein.ort,
|
||||
plz = verein.plz,
|
||||
strasse = verein.strasse,
|
||||
oepsRegionNummer = verein.oepsRegionNummer,
|
||||
istAktiv = verein.istAktiv,
|
||||
datenQuelle = verein.datenQuelle
|
||||
).withUpdatedTimestamp()
|
||||
@@ -207,9 +208,12 @@ class ZnsImportService(
|
||||
val pferd = ZnsLegacyParsers.parsePferd(zeile) ?: return@forEachIndexed
|
||||
if (pferd.pferdeName.isBlank()) return@forEachIndexed
|
||||
|
||||
// Match primarily by satznummer, then by lebensnummer, then by kopfnummer+name
|
||||
// Match primarily by satznummer, then by lebensnummer
|
||||
val vorhanden = pferd.satznummer?.takeIf { it.isNotBlank() }?.let { horseRepository.findBySatznummer(it) }
|
||||
?: pferd.lebensnummer?.takeIf { it.isNotBlank() }?.let { horseRepository.findByLebensnummer(it) }
|
||||
?: (if (pferd.pferdeName.isNotBlank()) horseRepository.findByName(pferd.pferdeName, 100).find {
|
||||
it.geburtsjahr == pferd.geburtsjahr && it.kopfnummer == pferd.kopfnummer
|
||||
} else null)
|
||||
|
||||
if (vorhanden == null) {
|
||||
horseRepository.save(pferd)
|
||||
@@ -253,7 +257,7 @@ class ZnsImportService(
|
||||
zeilen.forEachIndexed { index, zeile ->
|
||||
runCatching {
|
||||
val funktionaer = ZnsLegacyParsers.parseFunktionaer(zeile) ?: return@forEachIndexed
|
||||
val satzID = funktionaer.satzID
|
||||
val satzID = funktionaer.satzId
|
||||
val satzNummer = funktionaer.satzNummer
|
||||
val vorhanden = funktionaerRepository.findBySatz(satzID, satzNummer)
|
||||
if (vorhanden == null) {
|
||||
@@ -262,8 +266,6 @@ class ZnsImportService(
|
||||
} else {
|
||||
funktionaerRepository.save(
|
||||
vorhanden.copy(
|
||||
satzID = satzID,
|
||||
satzNummer = satzNummer,
|
||||
name = funktionaer.name,
|
||||
qualifikationen = funktionaer.qualifikationen,
|
||||
istAktiv = funktionaer.istAktiv,
|
||||
|
||||
+41
-21
@@ -1,9 +1,9 @@
|
||||
package at.mocode.zns.importer
|
||||
|
||||
import at.mocode.masterdata.domain.model.DomFunktionaer
|
||||
import at.mocode.masterdata.domain.model.DomPferd
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.DomVerein
|
||||
import at.mocode.masterdata.domain.model.Funktionaer
|
||||
import at.mocode.masterdata.domain.model.Pferd
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.model.Verein
|
||||
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
||||
import at.mocode.masterdata.domain.repository.HorseRepository
|
||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||
@@ -113,29 +113,29 @@ class ZnsImportServiceTest {
|
||||
val zip = buildZip("VEREIN01.DAT" to vereinZeile())
|
||||
|
||||
coEvery { vereinRepository.findByVereinsNummer(any()) } returns null
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<DomVerein>() }
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<Verein>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.vereineImportiert).isEqualTo(1)
|
||||
assertThat(result.vereineAktualisiert).isEqualTo(0)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 1) { vereinRepository.save(any<DomVerein>()) }
|
||||
coVerify(exactly = 1) { vereinRepository.save(any<Verein>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `importiereZip - bestehende Vereine werden aktualisiert`() = runTest {
|
||||
val zip = buildZip("VEREIN01.DAT" to vereinZeile(name = "Neuer Name"))
|
||||
val vorhanden = DomVerein(vereinsNummer = "0001", name = "Alter Name")
|
||||
val vorhanden = Verein(vereinsNummer = "0001", vereinName = "Alter Name")
|
||||
|
||||
coEvery { vereinRepository.findByVereinsNummer("0001") } returns vorhanden
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<DomVerein>() }
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<Verein>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.vereineImportiert).isEqualTo(0)
|
||||
assertThat(result.vereineAktualisiert).isEqualTo(1)
|
||||
coVerify(exactly = 1) { vereinRepository.save(match { it.name == "Neuer Name" }) }
|
||||
coVerify(exactly = 1) { vereinRepository.save(match { it.vereinName == "Neuer Name" }) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -143,14 +143,14 @@ class ZnsImportServiceTest {
|
||||
val zip = buildZip("LIZENZ01.DAT" to lizenzZeile())
|
||||
|
||||
coEvery { reiterRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { reiterRepository.save(any()) } answers { firstArg<DomReiter>() }
|
||||
coEvery { reiterRepository.save(any()) } answers { firstArg<Reiter>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.reiterImportiert).isEqualTo(1)
|
||||
assertThat(result.reiterAktualisiert).isEqualTo(0)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 1) { reiterRepository.save(any<DomReiter>()) }
|
||||
coVerify(exactly = 1) { reiterRepository.save(any<Reiter>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -159,14 +159,34 @@ class ZnsImportServiceTest {
|
||||
|
||||
coEvery { horseRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { horseRepository.findByLebensnummer(any()) } returns null
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<DomPferd>() }
|
||||
coEvery { horseRepository.findByName(any(), any()) } returns emptyList()
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<Pferd>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.pferdeImportiert).isEqualTo(1)
|
||||
assertThat(result.pferdeAktualisiert).isEqualTo(0)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 1) { horseRepository.save(any<DomPferd>()) }
|
||||
coVerify(exactly = 1) { horseRepository.save(any<Pferd>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `importiereZip - Pferde werden ueber Kopfnummer und Geburtsjahr aktualisiert, wenn Satznummer fehlt`() = runTest {
|
||||
// Zeile ohne Satznummer (zu kurz)
|
||||
val zeile = "0001Blitz "
|
||||
val zip = buildZip("PFERDE01.DAT" to zeile)
|
||||
|
||||
val existing = Pferd(pferdeName = "Blitz", kopfnummer = "0001", geschlecht = at.mocode.core.domain.model.PferdeGeschlechtE.UNBEKANNT)
|
||||
|
||||
coEvery { horseRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { horseRepository.findByLebensnummer(any()) } returns null
|
||||
coEvery { horseRepository.findByName("Blitz", 100) } returns listOf(existing)
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<Pferd>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.pferdeAktualisiert).isEqualTo(1)
|
||||
coVerify(exactly = 1) { horseRepository.save(match { it.pferdeName == "Blitz" && it.pferdId == existing.pferdId }) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -174,14 +194,14 @@ class ZnsImportServiceTest {
|
||||
val zip = buildZip("RICHT01.DAT" to funktionaerZeile())
|
||||
|
||||
coEvery { funktionaerRepository.findBySatz(any(), any()) } returns null
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<DomFunktionaer>() }
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<Funktionaer>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.richterImportiert).isEqualTo(1)
|
||||
assertThat(result.richterAktualisiert).isEqualTo(0)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 1) { funktionaerRepository.save(any<DomFunktionaer>()) }
|
||||
coVerify(exactly = 1) { funktionaerRepository.save(any<Funktionaer>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -192,13 +212,13 @@ class ZnsImportServiceTest {
|
||||
)
|
||||
|
||||
coEvery { funktionaerRepository.findBySatz(any(), any()) } returns null
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<DomFunktionaer>() }
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<Funktionaer>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
assertThat(result.richterImportiert).isEqualTo(4)
|
||||
assertThat(result.fehler).isEmpty()
|
||||
coVerify(exactly = 4) { funktionaerRepository.save(any<DomFunktionaer>()) }
|
||||
coVerify(exactly = 4) { funktionaerRepository.save(any<Funktionaer>()) }
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -211,14 +231,14 @@ class ZnsImportServiceTest {
|
||||
)
|
||||
|
||||
coEvery { vereinRepository.findByVereinsNummer(any()) } returns null
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<DomVerein>() }
|
||||
coEvery { vereinRepository.save(any()) } answers { firstArg<Verein>() }
|
||||
coEvery { reiterRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { reiterRepository.save(any()) } answers { firstArg<DomReiter>() }
|
||||
coEvery { reiterRepository.save(any()) } answers { firstArg<Reiter>() }
|
||||
coEvery { horseRepository.findBySatznummer(any()) } returns null
|
||||
coEvery { horseRepository.findByLebensnummer(any()) } returns null
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<DomPferd>() }
|
||||
coEvery { horseRepository.save(any()) } answers { firstArg<Pferd>() }
|
||||
coEvery { funktionaerRepository.findBySatz(any(), any()) } returns null
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<DomFunktionaer>() }
|
||||
coEvery { funktionaerRepository.save(any()) } answers { firstArg<Funktionaer>() }
|
||||
|
||||
val result = service.importiereZip(zip)
|
||||
|
||||
|
||||
+27
-27
@@ -2,7 +2,7 @@
|
||||
|
||||
package at.mocode.entries.api
|
||||
|
||||
import at.mocode.core.domain.model.NennungsStatusE
|
||||
import at.mocode.core.domain.model.NennStatusE
|
||||
import at.mocode.core.domain.model.StartwunschE
|
||||
import at.mocode.core.domain.serialization.UuidSerializer
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -13,28 +13,28 @@ import kotlin.uuid.Uuid
|
||||
*/
|
||||
@Serializable
|
||||
data class NennungDetailDto(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val nennungId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val abteilungId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val bewerbId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val turnierId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val reiterId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val pferdId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val zahlerId: Uuid? = null,
|
||||
val status: NennungsStatusE,
|
||||
val startwunsch: StartwunschE,
|
||||
val istNachnennung: Boolean,
|
||||
val nachnenngebuehrErlassen: Boolean,
|
||||
val isNachnenngebuehrFaellig: Boolean,
|
||||
val bemerkungen: String? = null,
|
||||
val createdAt: String,
|
||||
val updatedAt: String
|
||||
val status: NennStatusE,
|
||||
val startwunsch: StartwunschE,
|
||||
val istNachnennung: Boolean,
|
||||
val nachnenngebuehrErlassen: Boolean,
|
||||
val isNachnenngebuehrFaellig: Boolean,
|
||||
val bemerkungen: String? = null,
|
||||
val createdAt: String,
|
||||
val updatedAt: String
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -42,21 +42,21 @@ data class NennungDetailDto(
|
||||
*/
|
||||
@Serializable
|
||||
data class NennungSummaryDto(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val nennungId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val turnierId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val bewerbId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val abteilungId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val reiterId: Uuid,
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val pferdId: Uuid,
|
||||
val status: NennungsStatusE,
|
||||
val istNachnennung: Boolean,
|
||||
val createdAt: String
|
||||
val status: NennStatusE,
|
||||
val istNachnennung: Boolean,
|
||||
val createdAt: String
|
||||
)
|
||||
|
||||
/**
|
||||
@@ -86,8 +86,8 @@ data class NennungEinreichenRequest(
|
||||
*/
|
||||
@Serializable
|
||||
data class NennungStatusAendernRequest(
|
||||
val neuerStatus: NennungsStatusE,
|
||||
val bemerkungen: String? = null
|
||||
val neuerStatus: NennStatusE,
|
||||
val bemerkungen: String? = null
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
+6
-6
@@ -2,7 +2,7 @@
|
||||
|
||||
package at.mocode.entries.domain.model
|
||||
|
||||
import at.mocode.core.domain.model.NennungsStatusE
|
||||
import at.mocode.core.domain.model.NennStatusE
|
||||
import at.mocode.core.domain.model.StartwunschE
|
||||
import at.mocode.core.domain.serialization.InstantSerializer
|
||||
import at.mocode.core.domain.serialization.UuidSerializer
|
||||
@@ -28,8 +28,8 @@ import kotlin.uuid.Uuid
|
||||
* @property abteilungId Reference to the Abteilung (smallest entry unit).
|
||||
* @property bewerbId Reference to the parent Bewerb (for display/reporting).
|
||||
* @property turnierId Reference to the Turnier.
|
||||
* @property reiterId Reference to the DomReiter (actor-context).
|
||||
* @property pferdId Reference to the DomPferd (actor-context).
|
||||
* @property reiterId Reference to the Reiter (actor-context).
|
||||
* @property pferdId Reference to the Pferd (actor-context).
|
||||
* @property zahlerId Reference to the payer (may differ from rider, e.g. club pays).
|
||||
* @property status Current status of this entry.
|
||||
* @property startwunsch Rider's preferred starting position (vorne/hinten).
|
||||
@@ -63,7 +63,7 @@ data class DomNennung(
|
||||
val zahlerId: Uuid? = null,
|
||||
|
||||
// Entry Details
|
||||
val status: NennungsStatusE = NennungsStatusE.EINGEGANGEN,
|
||||
val status: NennStatusE = NennStatusE.EINGEGANGEN,
|
||||
val startwunsch: StartwunschE = StartwunschE.KEIN_WUNSCH,
|
||||
|
||||
// Late Entry (Nachnennung)
|
||||
@@ -83,8 +83,8 @@ data class DomNennung(
|
||||
* Checks if this entry is still active (not withdrawn or cancelled).
|
||||
*/
|
||||
fun isAktiv(): Boolean = status !in listOf(
|
||||
NennungsStatusE.ZURUECKGEZOGEN,
|
||||
NennungsStatusE.NICHT_ANGETRETEN
|
||||
NennStatusE.ZURUECKGEZOGEN,
|
||||
NennStatusE.NICHT_ANGETRETEN
|
||||
)
|
||||
|
||||
/**
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
package at.mocode.entries.domain.repository
|
||||
|
||||
import at.mocode.core.domain.model.NennungsStatusE
|
||||
import at.mocode.core.domain.model.NennStatusE
|
||||
import at.mocode.entries.domain.model.DomNennung
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
@@ -52,7 +52,7 @@ interface NennungRepository {
|
||||
/**
|
||||
* Sucht alle Nennungen mit einem bestimmten Status.
|
||||
*/
|
||||
suspend fun findByStatus(status: NennungsStatusE): List<DomNennung>
|
||||
suspend fun findByStatus(status: NennStatusE): List<DomNennung>
|
||||
|
||||
/**
|
||||
* Sucht alle Nachnennungen für einen Bewerb.
|
||||
@@ -84,5 +84,5 @@ interface NennungRepository {
|
||||
/**
|
||||
* Zählt alle Nennungen für ein Turnier mit einem bestimmten Status.
|
||||
*/
|
||||
suspend fun countByTurnierIdAndStatus(turnierId: Uuid, status: NennungsStatusE): Long
|
||||
suspend fun countByTurnierIdAndStatus(turnierId: Uuid, status: NennStatusE): Long
|
||||
}
|
||||
|
||||
+7
-7
@@ -3,12 +3,12 @@
|
||||
package at.mocode.entries.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.AbteilungsTeilungsTypE
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.model.PruefungsTypE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.entries.domain.model.DomAbteilung
|
||||
import at.mocode.entries.domain.model.DomBewerb
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
|
||||
/**
|
||||
* Service für die Anwendung der Abteilungs-Regeln gemäß ÖTO § 39.
|
||||
@@ -37,14 +37,14 @@ class AbteilungsRegelService {
|
||||
fun bestimmeAbteilung(
|
||||
bewerb: DomBewerb,
|
||||
abteilungen: List<DomAbteilung>,
|
||||
reiter: DomReiter
|
||||
reiter: Reiter
|
||||
): DomAbteilung? {
|
||||
if (abteilungen.isEmpty()) return null
|
||||
if (abteilungen.size == 1) return abteilungen.first()
|
||||
|
||||
return when (bewerb.teilungsTyp) {
|
||||
AbteilungsTeilungsTypE.NACH_LIZENZ -> {
|
||||
val istLizenzfrei = reiter.lizenzKlasse == LizenzKlasseE.LIZENZFREI
|
||||
val istLizenzfrei = reiter.lizenzKlasse == ReiterLizenzKlasseE.LIZENZFREI
|
||||
if (istLizenzfrei) {
|
||||
// Suche Abteilung für Lizenzfreie (oft Abt. 1 oder explizit benannt)
|
||||
abteilungen.find { it.bezeichnung?.contains("frei", ignoreCase = true) == true }
|
||||
@@ -61,7 +61,7 @@ class AbteilungsRegelService {
|
||||
AbteilungsTeilungsTypE.STRUKTURELL -> {
|
||||
// Bei strukturellen Teilungen (z.B. Caprilli oder CSN-C-NEU)
|
||||
if (bewerb.pruefungsTyp == PruefungsTypE.CAPRILLI) {
|
||||
val istLizenzfrei = reiter.lizenzKlasse == LizenzKlasseE.LIZENZFREI
|
||||
val istLizenzfrei = reiter.lizenzKlasse == ReiterLizenzKlasseE.LIZENZFREI
|
||||
if (istLizenzfrei) abteilungen.find { it.abteilungsNummer == 1 }
|
||||
else abteilungen.find { it.abteilungsNummer == 2 }
|
||||
} else if (bewerb.sparte == SparteE.SPRINGEN && bewerb.hoeheCm != null) {
|
||||
@@ -70,7 +70,7 @@ class AbteilungsRegelService {
|
||||
// ≥ 100 cm: nur R1+ erlaubt → alle in Abt. 1 (R1/R2+)
|
||||
val hoehe = bewerb.hoeheCm!!
|
||||
if (hoehe <= 95) {
|
||||
val istLizenzfrei = reiter.lizenzKlasse == LizenzKlasseE.LIZENZFREI
|
||||
val istLizenzfrei = reiter.lizenzKlasse == ReiterLizenzKlasseE.LIZENZFREI
|
||||
if (istLizenzfrei) {
|
||||
abteilungen.find { it.bezeichnung?.contains("ohne", ignoreCase = true) == true }
|
||||
?: abteilungen.minByOrNull { it.abteilungsNummer }
|
||||
@@ -80,7 +80,7 @@ class AbteilungsRegelService {
|
||||
}
|
||||
} else {
|
||||
// ≥ 100 cm: Pflicht-Teilung R1 / R2+
|
||||
val istR1 = reiter.lizenzKlasse == LizenzKlasseE.R1
|
||||
val istR1 = reiter.lizenzKlasse == ReiterLizenzKlasseE.R1
|
||||
if (istR1) {
|
||||
abteilungen.find { it.bezeichnung?.contains("R1", ignoreCase = false) == true }
|
||||
?: abteilungen.minByOrNull { it.abteilungsNummer }
|
||||
|
||||
+12
-12
@@ -5,7 +5,7 @@ package at.mocode.entries.domain.service
|
||||
import at.mocode.core.domain.model.*
|
||||
import at.mocode.entries.domain.model.DomAbteilung
|
||||
import at.mocode.entries.domain.model.DomBewerb
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.uuid.Uuid
|
||||
@@ -30,7 +30,7 @@ class AbteilungsRegelServiceTest {
|
||||
val abt1 = createAbteilung(bewerb.bewerbId, 1, "lizenzfrei")
|
||||
val abt2 = createAbteilung(bewerb.bewerbId, 2, "R1 und hoeher")
|
||||
|
||||
val reiter = createReiter(lizenzKlasse = LizenzKlasseE.LIZENZFREI)
|
||||
val reiter = createReiter(lizenzKlasse = ReiterLizenzKlasseE.LIZENZFREI)
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abt1, abt2), reiter)
|
||||
|
||||
@@ -43,7 +43,7 @@ class AbteilungsRegelServiceTest {
|
||||
val abt1 = createAbteilung(bewerb.bewerbId, 1, "lizenzfrei")
|
||||
val abt2 = createAbteilung(bewerb.bewerbId, 2, "Lizenz")
|
||||
|
||||
val reiter = createReiter(lizenzKlasse = LizenzKlasseE.R1)
|
||||
val reiter = createReiter(lizenzKlasse = ReiterLizenzKlasseE.R1)
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abt1, abt2), reiter)
|
||||
|
||||
@@ -68,7 +68,7 @@ class AbteilungsRegelServiceTest {
|
||||
val bewerb = createBewerb(teilungsTyp = AbteilungsTeilungsTypE.STRUKTURELL, hoeheCm = 95)
|
||||
val abtOhne = createAbteilung(bewerb.bewerbId, 1, "ohne Lizenz")
|
||||
val abtMit = createAbteilung(bewerb.bewerbId, 2, "mit Lizenz")
|
||||
val reiter = createReiter(LizenzKlasseE.LIZENZFREI)
|
||||
val reiter = createReiter(ReiterLizenzKlasseE.LIZENZFREI)
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abtOhne, abtMit), reiter)
|
||||
|
||||
@@ -80,7 +80,7 @@ class AbteilungsRegelServiceTest {
|
||||
val bewerb = createBewerb(teilungsTyp = AbteilungsTeilungsTypE.STRUKTURELL, hoeheCm = 95)
|
||||
val abtOhne = createAbteilung(bewerb.bewerbId, 1, "ohne Lizenz")
|
||||
val abtMit = createAbteilung(bewerb.bewerbId, 2, "mit Lizenz")
|
||||
val reiter = createReiter(LizenzKlasseE.R1)
|
||||
val reiter = createReiter(ReiterLizenzKlasseE.R1)
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abtOhne, abtMit), reiter)
|
||||
|
||||
@@ -93,7 +93,7 @@ class AbteilungsRegelServiceTest {
|
||||
val abtOhne = createAbteilung(bewerb.bewerbId, 1, "ohne Lizenz")
|
||||
val abtMit = createAbteilung(bewerb.bewerbId, 2, "mit Lizenz")
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abtOhne, abtMit), createReiter(LizenzKlasseE.LIZENZFREI))
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abtOhne, abtMit), createReiter(ReiterLizenzKlasseE.LIZENZFREI))
|
||||
|
||||
assertEquals(abtOhne.abteilungId, result?.abteilungId)
|
||||
}
|
||||
@@ -105,7 +105,7 @@ class AbteilungsRegelServiceTest {
|
||||
val bewerb = createBewerb(teilungsTyp = AbteilungsTeilungsTypE.STRUKTURELL, hoeheCm = 100)
|
||||
val abtR1 = createAbteilung(bewerb.bewerbId, 1, "R1")
|
||||
val abtR2 = createAbteilung(bewerb.bewerbId, 2, "R2+")
|
||||
val reiter = createReiter(LizenzKlasseE.R1)
|
||||
val reiter = createReiter(ReiterLizenzKlasseE.R1)
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abtR1, abtR2), reiter)
|
||||
|
||||
@@ -117,7 +117,7 @@ class AbteilungsRegelServiceTest {
|
||||
val bewerb = createBewerb(teilungsTyp = AbteilungsTeilungsTypE.STRUKTURELL, hoeheCm = 100)
|
||||
val abtR1 = createAbteilung(bewerb.bewerbId, 1, "R1")
|
||||
val abtR2 = createAbteilung(bewerb.bewerbId, 2, "R2+")
|
||||
val reiter = createReiter(LizenzKlasseE.R2)
|
||||
val reiter = createReiter(ReiterLizenzKlasseE.R2)
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abtR1, abtR2), reiter)
|
||||
|
||||
@@ -130,7 +130,7 @@ class AbteilungsRegelServiceTest {
|
||||
val abtR1 = createAbteilung(bewerb.bewerbId, 1, "R1")
|
||||
val abtR2 = createAbteilung(bewerb.bewerbId, 2, "R2+")
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abtR1, abtR2), createReiter(LizenzKlasseE.R1))
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abtR1, abtR2), createReiter(ReiterLizenzKlasseE.R1))
|
||||
|
||||
assertEquals(abtR1.abteilungId, result?.abteilungId)
|
||||
}
|
||||
@@ -191,7 +191,7 @@ class AbteilungsRegelServiceTest {
|
||||
val abt1 = createAbteilung(bewerb.bewerbId, 1, "ohne Lizenz")
|
||||
val abt2 = createAbteilung(bewerb.bewerbId, 2, "mit Lizenz")
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abt1, abt2), createReiter(LizenzKlasseE.LIZENZFREI))
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abt1, abt2), createReiter(ReiterLizenzKlasseE.LIZENZFREI))
|
||||
|
||||
assertEquals(abt1.abteilungId, result?.abteilungId)
|
||||
}
|
||||
@@ -202,7 +202,7 @@ class AbteilungsRegelServiceTest {
|
||||
val abt1 = createAbteilung(bewerb.bewerbId, 1, "ohne Lizenz")
|
||||
val abt2 = createAbteilung(bewerb.bewerbId, 2, "mit Lizenz")
|
||||
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abt1, abt2), createReiter(LizenzKlasseE.R1))
|
||||
val result = service.bestimmeAbteilung(bewerb, listOf(abt1, abt2), createReiter(ReiterLizenzKlasseE.R1))
|
||||
|
||||
assertEquals(abt2.abteilungId, result?.abteilungId)
|
||||
}
|
||||
@@ -236,7 +236,7 @@ class AbteilungsRegelServiceTest {
|
||||
starterAnzahl = starterAnzahl
|
||||
)
|
||||
|
||||
private fun createReiter(lizenzKlasse: LizenzKlasseE = LizenzKlasseE.LIZENZFREI) = DomReiter(
|
||||
private fun createReiter(lizenzKlasse: ReiterLizenzKlasseE = ReiterLizenzKlasseE.LIZENZFREI) = Reiter(
|
||||
personId = Uuid.random(),
|
||||
satznummer = "123456",
|
||||
nachname = "Mustermann",
|
||||
|
||||
+4
-4
@@ -2,7 +2,7 @@
|
||||
|
||||
package at.mocode.entries.service.persistence
|
||||
|
||||
import at.mocode.core.domain.model.NennungsStatusE
|
||||
import at.mocode.core.domain.model.NennStatusE
|
||||
import at.mocode.core.domain.model.StartwunschE
|
||||
import at.mocode.entries.domain.model.DomNennung
|
||||
import at.mocode.entries.domain.repository.NennungRepository
|
||||
@@ -32,7 +32,7 @@ class NennungRepositoryImpl : NennungRepository {
|
||||
reiterId = row[NennungTable.reiterId].toKotlinUuid(),
|
||||
pferdId = row[NennungTable.pferdId].toKotlinUuid(),
|
||||
zahlerId = row[NennungTable.zahlerId]?.toKotlinUuid(),
|
||||
status = NennungsStatusE.valueOf(row[NennungTable.status]),
|
||||
status = NennStatusE.valueOf(row[NennungTable.status]),
|
||||
startwunsch = StartwunschE.valueOf(row[NennungTable.startwunsch]),
|
||||
istNachnennung = row[NennungTable.istNachnennung],
|
||||
nachnenngebuehrErlassen = row[NennungTable.nachnenngebuehrErlassen],
|
||||
@@ -79,7 +79,7 @@ class NennungRepositoryImpl : NennungRepository {
|
||||
}.map(::rowToNennung)
|
||||
}
|
||||
|
||||
override suspend fun findByStatus(status: NennungsStatusE): List<DomNennung> = tenantTransaction {
|
||||
override suspend fun findByStatus(status: NennStatusE): List<DomNennung> = tenantTransaction {
|
||||
NennungTable.selectAll().where { NennungTable.status eq status.name }
|
||||
.map(::rowToNennung)
|
||||
}
|
||||
@@ -145,7 +145,7 @@ class NennungRepositoryImpl : NennungRepository {
|
||||
NennungTable.selectAll().where { NennungTable.abteilungId eq abteilungId.toJavaUuid() }.count()
|
||||
}
|
||||
|
||||
override suspend fun countByTurnierIdAndStatus(turnierId: Uuid, status: NennungsStatusE): Long = tenantTransaction {
|
||||
override suspend fun countByTurnierIdAndStatus(turnierId: Uuid, status: NennStatusE): Long = tenantTransaction {
|
||||
NennungTable.selectAll().where {
|
||||
(NennungTable.turnierId eq turnierId.toJavaUuid()) and
|
||||
(NennungTable.status eq status.name)
|
||||
|
||||
+3
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
package at.mocode.entries.service.usecase
|
||||
|
||||
import at.mocode.core.domain.model.NennungsStatusE
|
||||
import at.mocode.core.domain.model.NennStatusE
|
||||
import at.mocode.entries.api.*
|
||||
import at.mocode.entries.domain.model.DomNennung
|
||||
import at.mocode.entries.domain.model.DomNennungsTransfer
|
||||
@@ -101,7 +101,7 @@ class NennungUseCases(
|
||||
val nennung = nennungRepository.findById(nennungId)
|
||||
?: throw NoSuchElementException("Nennung nicht gefunden: $nennungId")
|
||||
|
||||
val updated = nennung.copy(status = NennungsStatusE.ZURUECKGEZOGEN).withUpdatedTimestamp()
|
||||
val updated = nennung.copy(status = NennStatusE.ZURUECKGEZOGEN).withUpdatedTimestamp()
|
||||
val saved = nennungRepository.save(updated)
|
||||
log.info("Nennung zurückgezogen: nennungId={}", nennungId)
|
||||
return saved.toDetailDto()
|
||||
@@ -131,7 +131,7 @@ class NennungUseCases(
|
||||
}
|
||||
|
||||
// 1. Ursprungs-Nennung schließen
|
||||
val geschlosseneNennung = ursprung.copy(status = NennungsStatusE.TRANSFERIERT).withUpdatedTimestamp()
|
||||
val geschlosseneNennung = ursprung.copy(status = NennStatusE.TRANSFERIERT).withUpdatedTimestamp()
|
||||
nennungRepository.save(geschlosseneNennung)
|
||||
|
||||
// 2. Neue Nennung anlegen
|
||||
|
||||
+1
-1
@@ -151,7 +151,7 @@ private fun DomNennung.Companion.random(now: kotlin.time.Instant): DomNennung {
|
||||
reiterId = Uuid.random(),
|
||||
pferdId = Uuid.random(),
|
||||
zahlerId = null,
|
||||
status = at.mocode.core.domain.model.NennungsStatusE.EINGEGANGEN,
|
||||
status = at.mocode.core.domain.model.NennStatusE.EINGEGANGEN,
|
||||
startwunsch = at.mocode.core.domain.model.StartwunschE.VORNE,
|
||||
istNachnennung = false,
|
||||
nachnenngebuehrErlassen = false,
|
||||
|
||||
+5
-5
@@ -3,7 +3,7 @@
|
||||
package at.mocode.masterdata.api.rest
|
||||
|
||||
import at.mocode.core.domain.serialization.InstantSerializer
|
||||
import at.mocode.masterdata.domain.model.DomFunktionaer
|
||||
import at.mocode.masterdata.domain.model.Funktionaer
|
||||
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.request.*
|
||||
@@ -96,8 +96,8 @@ class FunktionaerController(private val funktionaerRepository: FunktionaerReposi
|
||||
*/
|
||||
post {
|
||||
val req = call.receive<FunktionaerCreateRequest>()
|
||||
val domFunktionaer = DomFunktionaer(
|
||||
satzID = req.satzID,
|
||||
val domFunktionaer = Funktionaer(
|
||||
satzId = req.satzID,
|
||||
satzNummer = req.satzNummer,
|
||||
name = req.name,
|
||||
qualifikationen = req.qualifikationen,
|
||||
@@ -139,9 +139,9 @@ class FunktionaerController(private val funktionaerRepository: FunktionaerReposi
|
||||
|
||||
private fun parseUuid(value: String?): Uuid? = value?.let { runCatching { Uuid.parse(it) }.getOrNull() }
|
||||
|
||||
private fun DomFunktionaer.toDto() = FunktionaerDto(
|
||||
private fun Funktionaer.toDto() = FunktionaerDto(
|
||||
funktionaerId = funktionaerId.toString(),
|
||||
satzID = satzID,
|
||||
satzID = satzId,
|
||||
satzNummer = satzNummer,
|
||||
name = name,
|
||||
qualifikationen = qualifikationen,
|
||||
|
||||
+4
-4
@@ -4,7 +4,7 @@ package at.mocode.masterdata.api.rest
|
||||
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.core.domain.serialization.InstantSerializer
|
||||
import at.mocode.masterdata.domain.model.DomPferd
|
||||
import at.mocode.masterdata.domain.model.Pferd
|
||||
import at.mocode.masterdata.domain.repository.HorseRepository
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.request.*
|
||||
@@ -110,7 +110,7 @@ class HorseController(private val horseRepository: HorseRepository) {
|
||||
val req = call.receive<HorseCreateRequest>()
|
||||
val geschlecht = runCatching { PferdeGeschlechtE.valueOf(req.geschlecht) }.getOrNull()
|
||||
?: return@post call.respond(HttpStatusCode.BadRequest, "Ungültiges Geschlecht: ${req.geschlecht}")
|
||||
val domPferd = DomPferd(
|
||||
val pferd = Pferd(
|
||||
kopfnummer = req.kopfnummer,
|
||||
pferdeName = req.pferdeName,
|
||||
lebensnummer = req.lebensnummer,
|
||||
@@ -120,7 +120,7 @@ class HorseController(private val horseRepository: HorseRepository) {
|
||||
satznummer = req.satznummer,
|
||||
istAktiv = req.istAktiv
|
||||
)
|
||||
val saved = horseRepository.save(domPferd)
|
||||
val saved = horseRepository.save(pferd)
|
||||
call.respond(HttpStatusCode.Created, saved.toDto())
|
||||
}
|
||||
|
||||
@@ -161,7 +161,7 @@ class HorseController(private val horseRepository: HorseRepository) {
|
||||
|
||||
private fun parseUuid(value: String?): Uuid? = value?.let { runCatching { Uuid.parse(it) }.getOrNull() }
|
||||
|
||||
private fun DomPferd.toDto() = HorseDto(
|
||||
private fun Pferd.toDto() = HorseDto(
|
||||
pferdId = pferdId.toString(),
|
||||
kopfnummer = kopfnummer,
|
||||
pferdeName = pferdeName,
|
||||
|
||||
+6
-6
@@ -2,10 +2,10 @@
|
||||
|
||||
package at.mocode.masterdata.api.rest
|
||||
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.serialization.InstantSerializer
|
||||
import at.mocode.core.domain.serialization.LocalDateSerializer
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.request.*
|
||||
@@ -132,9 +132,9 @@ class ReiterController(private val reiterRepository: ReiterRepository) {
|
||||
*/
|
||||
post {
|
||||
val req = call.receive<ReiterCreateRequest>()
|
||||
val lizenzKlasse = runCatching { LizenzKlasseE.valueOf(req.lizenzKlasse) }.getOrNull()
|
||||
val lizenzKlasse = runCatching { ReiterLizenzKlasseE.valueOf(req.lizenzKlasse) }.getOrNull()
|
||||
?: return@post call.respond(HttpStatusCode.BadRequest, "Ungültige lizenzKlasse: ${req.lizenzKlasse}")
|
||||
val domReiter = DomReiter(
|
||||
val domReiter = Reiter(
|
||||
personId = Uuid.random(),
|
||||
satznummer = req.satznummer,
|
||||
nachname = req.nachname,
|
||||
@@ -165,7 +165,7 @@ class ReiterController(private val reiterRepository: ReiterRepository) {
|
||||
val existing = reiterRepository.findById(id) ?: return@put call.respond(HttpStatusCode.NotFound)
|
||||
val req = call.receive<ReiterUpdateRequest>()
|
||||
val lizenzKlasse = req.lizenzKlasse?.let {
|
||||
runCatching { LizenzKlasseE.valueOf(it) }.getOrNull()
|
||||
runCatching { ReiterLizenzKlasseE.valueOf(it) }.getOrNull()
|
||||
?: return@put call.respond(HttpStatusCode.BadRequest, "Ungültige lizenzKlasse: $it")
|
||||
} ?: existing.lizenzKlasse
|
||||
val updated = existing.copy(
|
||||
@@ -202,7 +202,7 @@ class ReiterController(private val reiterRepository: ReiterRepository) {
|
||||
|
||||
private fun parseUuid(value: String?): Uuid? = value?.let { runCatching { Uuid.parse(it) }.getOrNull() }
|
||||
|
||||
private fun DomReiter.toDto() = ReiterDto(
|
||||
private fun Reiter.toDto() = ReiterDto(
|
||||
reiterId = reiterId.toString(),
|
||||
satznummer = satznummer,
|
||||
nachname = nachname,
|
||||
|
||||
+13
-19
@@ -3,7 +3,7 @@
|
||||
package at.mocode.masterdata.api.rest
|
||||
|
||||
import at.mocode.core.domain.serialization.InstantSerializer
|
||||
import at.mocode.masterdata.domain.model.DomVerein
|
||||
import at.mocode.masterdata.domain.model.Verein
|
||||
import at.mocode.masterdata.domain.repository.VereinRepository
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.request.*
|
||||
@@ -24,7 +24,6 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
val vereinId: String,
|
||||
val vereinsNummer: String,
|
||||
val name: String,
|
||||
val kurzname: String? = null,
|
||||
val bundesland: String? = null,
|
||||
val ort: String? = null,
|
||||
val plz: String? = null,
|
||||
@@ -32,9 +31,9 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
val email: String? = null,
|
||||
val telefon: String? = null,
|
||||
val website: String? = null,
|
||||
val oepsRegionNummer: String? = null,
|
||||
val istVeranstalter: Boolean,
|
||||
val istAktiv: Boolean,
|
||||
val imageUrl: String? = null,
|
||||
val bemerkungen: String? = null,
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
val updatedAt: Instant
|
||||
@@ -44,7 +43,6 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
data class VereinCreateRequest(
|
||||
val vereinsNummer: String,
|
||||
val name: String,
|
||||
val kurzname: String? = null,
|
||||
val bundesland: String? = null,
|
||||
val ort: String? = null,
|
||||
val plz: String? = null,
|
||||
@@ -52,16 +50,15 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
val email: String? = null,
|
||||
val telefon: String? = null,
|
||||
val website: String? = null,
|
||||
val oepsRegionNummer: String? = null,
|
||||
val istVeranstalter: Boolean = false,
|
||||
val istAktiv: Boolean = true,
|
||||
val imageUrl: String? = null,
|
||||
val bemerkungen: String? = null
|
||||
)
|
||||
|
||||
@Serializable
|
||||
data class VereinUpdateRequest(
|
||||
val name: String? = null,
|
||||
val kurzname: String? = null,
|
||||
val bundesland: String? = null,
|
||||
val ort: String? = null,
|
||||
val plz: String? = null,
|
||||
@@ -69,9 +66,9 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
val email: String? = null,
|
||||
val telefon: String? = null,
|
||||
val website: String? = null,
|
||||
val oepsRegionNummer: String? = null,
|
||||
val istVeranstalter: Boolean? = null,
|
||||
val istAktiv: Boolean? = null,
|
||||
val imageUrl: String? = null,
|
||||
val bemerkungen: String? = null
|
||||
)
|
||||
|
||||
@@ -95,7 +92,7 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
}
|
||||
|
||||
/**
|
||||
* GET /verein/search?q=... — Sucht Vereine nach Name oder Kurzname.
|
||||
* GET /verein/search?q=... — Sucht Vereine nach Name.
|
||||
*/
|
||||
get("/search") {
|
||||
val query = call.request.queryParameters["q"] ?: ""
|
||||
@@ -126,10 +123,9 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
*/
|
||||
post {
|
||||
val req = call.receive<VereinCreateRequest>()
|
||||
val domVerein = DomVerein(
|
||||
val domVerein = Verein(
|
||||
vereinsNummer = req.vereinsNummer,
|
||||
name = req.name,
|
||||
kurzname = req.kurzname,
|
||||
vereinName = req.name,
|
||||
bundesland = req.bundesland,
|
||||
ort = req.ort,
|
||||
plz = req.plz,
|
||||
@@ -137,9 +133,9 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
email = req.email,
|
||||
telefon = req.telefon,
|
||||
website = req.website,
|
||||
oepsRegionNummer = req.oepsRegionNummer,
|
||||
istVeranstalter = req.istVeranstalter,
|
||||
istAktiv = req.istAktiv,
|
||||
imageUrl = req.imageUrl,
|
||||
bemerkungen = req.bemerkungen
|
||||
)
|
||||
val saved = vereinRepository.save(domVerein)
|
||||
@@ -154,8 +150,7 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
val existing = vereinRepository.findById(id) ?: return@put call.respond(HttpStatusCode.NotFound)
|
||||
val req = call.receive<VereinUpdateRequest>()
|
||||
val updated = existing.copy(
|
||||
name = req.name ?: existing.name,
|
||||
kurzname = req.kurzname ?: existing.kurzname,
|
||||
vereinName = req.name ?: existing.vereinName,
|
||||
bundesland = req.bundesland ?: existing.bundesland,
|
||||
ort = req.ort ?: existing.ort,
|
||||
plz = req.plz ?: existing.plz,
|
||||
@@ -163,9 +158,9 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
email = req.email ?: existing.email,
|
||||
telefon = req.telefon ?: existing.telefon,
|
||||
website = req.website ?: existing.website,
|
||||
oepsRegionNummer = req.oepsRegionNummer ?: existing.oepsRegionNummer,
|
||||
istVeranstalter = req.istVeranstalter ?: existing.istVeranstalter,
|
||||
istAktiv = req.istAktiv ?: existing.istAktiv,
|
||||
imageUrl = req.imageUrl ?: existing.imageUrl,
|
||||
bemerkungen = req.bemerkungen ?: existing.bemerkungen
|
||||
)
|
||||
val saved = vereinRepository.save(updated)
|
||||
@@ -185,11 +180,10 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
|
||||
private fun parseUuid(value: String?): Uuid? = value?.let { runCatching { Uuid.parse(it) }.getOrNull() }
|
||||
|
||||
private fun DomVerein.toDto() = VereinDto(
|
||||
private fun Verein.toDto() = VereinDto(
|
||||
vereinId = vereinId.toString(),
|
||||
vereinsNummer = vereinsNummer,
|
||||
name = name,
|
||||
kurzname = kurzname,
|
||||
name = vereinName,
|
||||
bundesland = bundesland,
|
||||
ort = ort,
|
||||
plz = plz,
|
||||
@@ -197,9 +191,9 @@ class VereinController(private val vereinRepository: VereinRepository) {
|
||||
email = email,
|
||||
telefon = telefon,
|
||||
website = website,
|
||||
oepsRegionNummer = oepsRegionNummer,
|
||||
istVeranstalter = istVeranstalter,
|
||||
istAktiv = istAktiv,
|
||||
imageUrl = imageUrl,
|
||||
bemerkungen = bemerkungen,
|
||||
updatedAt = updatedAt
|
||||
)
|
||||
|
||||
+34
-16
@@ -18,7 +18,7 @@ import kotlin.uuid.Uuid
|
||||
* aus dem ZNS geprüft.
|
||||
*
|
||||
* @property funktionaerId Eindeutige interne ID (UUID).
|
||||
* @property satzID Typ des Satzes (X = Richter, Y = Parcoursbauer). Aus ZNS (RICHT01.DAT / PARCO01.DAT).
|
||||
* @property satzId Typ des Satzes (X = Richter, Y = Parcoursbauer). Aus ZNS (RICHT01.DAT / PARCO01.DAT).
|
||||
* @property satzNummer Satznummer (6-stellig). Aus ZNS (RICHT01.DAT / PARCO01.DAT).
|
||||
* @property name Vollständiger Name (Nachname, Vorname). Aus ZNS (RICHT01.DAT / PARCO01.DAT).
|
||||
* @property qualifikation Qualifikationen (getrennt durch `,`). Aus ZNS (RICHT01.DAT / PARCO01.DAT).
|
||||
@@ -29,24 +29,42 @@ import kotlin.uuid.Uuid
|
||||
* @property updatedAt Letzter Änderungszeitpunkt.
|
||||
*/
|
||||
@Serializable
|
||||
data class DomFunktionaer(
|
||||
data class Funktionaer(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val funktionaerId: Uuid = Uuid.random(),
|
||||
val satzID: String,
|
||||
|
||||
// Reference to base person
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val personId: Uuid? = null,
|
||||
|
||||
// === ZNS.zip RICHT01.DAT === ANFANG ===
|
||||
|
||||
// Alphanumerisch (1) WERT "X" = RICHTER, "Y" = PARCOURSBAUER
|
||||
var satzId: String,
|
||||
|
||||
// Numerisch (6) FORMAT: 000000
|
||||
val satzNummer: Int,
|
||||
|
||||
// Alphanumerisch (75)
|
||||
var name: String? = null, // Nachname, Vorname
|
||||
|
||||
// Alphanumerisch (30+)
|
||||
var qualifikationen: List<String> = emptyList(), // Liste der Qualifikations-Kürzel
|
||||
|
||||
// var vorname: String,
|
||||
// var nachname: String,
|
||||
// var geburtsdatum: LocalDate? = null,
|
||||
// val richterNummer: String? = null,
|
||||
// var rollen: Set<FunktionaerRolleE> = emptySet(),
|
||||
// var richterQualifikation: RichterQualifikationE? = null,
|
||||
// var qualifiziertFuerSparten: Set<SparteE> = emptySet(),
|
||||
// var email: String? = null,
|
||||
// var telefon: String? = null,
|
||||
// var vereinsNummer: String? = null,
|
||||
// === ZNS.zip RICHT01.DAT === ENDE ===
|
||||
|
||||
// Kontakt
|
||||
var imageUrl: String? = null,
|
||||
var email: String? = null,
|
||||
var telefon: String? = null,
|
||||
var website: String? = null,
|
||||
|
||||
// Adresse
|
||||
var strasse: String? = null,
|
||||
var hausnummer: String? = null,
|
||||
var ort: String? = null,
|
||||
var plz: String? = null,
|
||||
var bundesland: String? = null,
|
||||
|
||||
// Status & Verwaltung
|
||||
var istAktiv: Boolean = true,
|
||||
@@ -73,12 +91,12 @@ data class DomFunktionaer(
|
||||
/**
|
||||
* Prüft, ob der Funktionär als Richter qualifiziert ist.
|
||||
*/
|
||||
fun istRichter(): Boolean = satzID.uppercase() == "X"
|
||||
fun istRichter(): Boolean = satzId.uppercase() == "X"
|
||||
|
||||
/**
|
||||
* Prüft, ob der Funktionär als Parcoursbauer qualifiziert ist.
|
||||
*/
|
||||
fun istParcoursbauer(): Boolean = satzID.uppercase() == "Y"
|
||||
fun istParcoursbauer(): Boolean = satzId.uppercase() == "Y"
|
||||
|
||||
/**
|
||||
* Validiert die Pflichtfelder für den Turniereinsatz.
|
||||
@@ -97,5 +115,5 @@ data class DomFunktionaer(
|
||||
/**
|
||||
* Erstellt eine Kopie mit aktualisiertem Zeitstempel.
|
||||
*/
|
||||
fun withUpdatedTimestamp(): DomFunktionaer = this.copy(updatedAt = Clock.System.now())
|
||||
fun withUpdatedTimestamp(): Funktionaer = this.copy(updatedAt = Clock.System.now())
|
||||
}
|
||||
+10
-10
@@ -2,7 +2,7 @@
|
||||
|
||||
package at.mocode.masterdata.domain.model
|
||||
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.core.domain.serialization.InstantSerializer
|
||||
import at.mocode.core.domain.serialization.UuidSerializer
|
||||
@@ -15,20 +15,20 @@ import kotlin.uuid.Uuid
|
||||
*/
|
||||
@Serializable
|
||||
data class LicenseMatrixEntry(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val licenseId: Uuid = Uuid.random(),
|
||||
val sparte: SparteE,
|
||||
val lizenzKlasse: LizenzKlasseE,
|
||||
val maxTurnierklasseCode: String, // E, A, L, LM, M, S
|
||||
val sparte: SparteE,
|
||||
val lizenzKlasse: ReiterLizenzKlasseE,
|
||||
val maxTurnierklasseCode: String, // E, A, L, LM, M, S
|
||||
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
val validFrom: Instant,
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
val validTo: Instant? = null,
|
||||
|
||||
val istAktiv: Boolean = true,
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
val istAktiv: Boolean = true,
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
val createdAt: Instant,
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
val updatedAt: Instant
|
||||
)
|
||||
|
||||
+44
-18
@@ -4,6 +4,7 @@ package at.mocode.masterdata.domain.model
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.core.domain.serialization.InstantSerializer
|
||||
import at.mocode.core.domain.serialization.UuidSerializer
|
||||
import kotlinx.datetime.todayIn
|
||||
import kotlinx.serialization.Serializable
|
||||
@@ -39,42 +40,67 @@ import kotlin.uuid.Uuid
|
||||
* @property updatedAt Timestamp when this record was last updated.
|
||||
*/
|
||||
@Serializable
|
||||
data class DomPferd(
|
||||
data class Pferd(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val pferdId: Uuid = Uuid.random(),
|
||||
|
||||
// PFERDE01.DAT Information
|
||||
// Reference to base person
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val personId: Uuid? = null,
|
||||
|
||||
// === ZNS.zip PFERDE01.DAT === ANFANG ===
|
||||
|
||||
// Alphanumerisch (4)
|
||||
var kopfnummer: String? = null,
|
||||
|
||||
// Alphanumerisch (30)
|
||||
var pferdeName: String,
|
||||
|
||||
// Alphanumerisch (9) FORMAT: 000000000
|
||||
var lebensnummer: String? = null,
|
||||
|
||||
// Alphanumerisch (1)
|
||||
var geschlecht: PferdeGeschlechtE,
|
||||
|
||||
// Numerisch (4) FORMAT: 0000
|
||||
var geburtsjahr: Int? = null,
|
||||
|
||||
// Alphanumerisch (15)
|
||||
var farbe: String? = null,
|
||||
|
||||
// Alphanumerisch (15)
|
||||
var abstammung: String? = null,
|
||||
|
||||
// Numerisch (4) FORMAT: 0000
|
||||
var vereinNummer: Int? = null,
|
||||
|
||||
// Numerisch (4) FORMAT: 0000
|
||||
var lastPayYear: Int? = null,
|
||||
|
||||
// Alphanumerisch (75) Standard: BLANK
|
||||
var verantwortlichePersonId: String? = null,
|
||||
|
||||
// Alphanumerisch (30) Standard: BLANK
|
||||
var vater: String? = null,
|
||||
|
||||
// Alphanumerisch (10) Standard: BLANK
|
||||
var feiPass: String? = null,
|
||||
|
||||
// Alphanumerisch (10) FORMAT: 0000000000
|
||||
var satznummer: String? = null,
|
||||
|
||||
// var geburtsdatum: LocalDate? = null,
|
||||
// var rasse: String? = null,
|
||||
// @Serializable(with = UuidSerializer::class)
|
||||
// var besitzerId: Uuid? = null,
|
||||
// var zuechterName: String? = null,
|
||||
// var zuchtbuchNummer: String? = null,
|
||||
// var chipNummer: String? = null,
|
||||
// var passNummer: String? = null,
|
||||
// var oepsNummer: String? = null,
|
||||
// var mutterName: String? = null,
|
||||
// var mutterVaterName: String? = null,
|
||||
// var stockmass: Int? = null, // Height in cm
|
||||
// === ZNS.zip PFERDE01.DAT === ENDE ===
|
||||
|
||||
var istAktiv: Boolean = true,
|
||||
|
||||
// Status & Verwaltung
|
||||
val istAktiv: Boolean = true,
|
||||
var bemerkungen: String? = null,
|
||||
var datenQuelle: DatenQuelleE = DatenQuelleE.MANUELL,
|
||||
var createdAt: Instant = Clock.System.now(),
|
||||
val datenQuelle: DatenQuelleE = DatenQuelleE.IMPORT_ZNS,
|
||||
|
||||
// Audit
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
val createdAt: Instant = Clock.System.now(),
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
var updatedAt: Instant = Clock.System.now()
|
||||
) {
|
||||
/**
|
||||
@@ -141,7 +167,7 @@ data class DomPferd(
|
||||
/**
|
||||
* Creates a copy of this horse with an updated timestamp.
|
||||
*/
|
||||
fun withUpdatedTimestamp(): DomPferd {
|
||||
fun withUpdatedTimestamp(): Pferd {
|
||||
return this.copy(updatedAt = Clock.System.now())
|
||||
}
|
||||
}
|
||||
+73
-15
@@ -3,8 +3,7 @@
|
||||
package at.mocode.masterdata.domain.model
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.serialization.InstantSerializer
|
||||
import at.mocode.core.domain.serialization.LocalDateSerializer
|
||||
import at.mocode.core.domain.serialization.UuidSerializer
|
||||
@@ -51,42 +50,101 @@ import kotlin.uuid.Uuid
|
||||
* @property updatedAt Timestamp when this record was last updated.
|
||||
*/
|
||||
@Serializable
|
||||
data class DomReiter(
|
||||
data class Reiter(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val reiterId: Uuid = Uuid.random(),
|
||||
|
||||
// Reference to base person
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val personId: Uuid,
|
||||
val personId: Uuid? = null,
|
||||
|
||||
// ZNS Identification
|
||||
// === ZNS.zip LIZENZ01.DAT === ANFANG ===
|
||||
|
||||
// Alphanumerisch (6) FORMAT: 000000
|
||||
var satznummer: String?,
|
||||
|
||||
// Alphanumerisch (50)
|
||||
var nachname: String,
|
||||
|
||||
// Alphanumerisch (25)
|
||||
var vorname: String,
|
||||
|
||||
// Numerisch (2) FORMAT: 99
|
||||
var bundeslandNummer: Int? = null,
|
||||
|
||||
// Alphanumerisch (50)
|
||||
var vereinsName: String? = null,
|
||||
|
||||
// Alphanumerisch (3)
|
||||
var nation: String? = null,
|
||||
|
||||
// Alphanumerisch (4) Keine Lizenz: BLANK
|
||||
var reiterLizenz: String? = null,
|
||||
|
||||
// Alphanumerisch (1) Keine Startkarte: BLANK
|
||||
var startkarte: String? = null,
|
||||
|
||||
// Alphanumerisch (2) Keine Fahrlizenz: BLANK
|
||||
var fahrLizenz: String? = null,
|
||||
|
||||
// Alphanumerisch (2) WERTE: Standard: BLANK, JG=JUGENDLICHER, JR=JUNIOR, 25=U25
|
||||
var altersklasseJgJrU25: String? = null,
|
||||
|
||||
// Alphanumerisch (1) WERTE: Standard: BLANK Y=JUNGER-REITER
|
||||
var altersklasseY: String? = null,
|
||||
|
||||
// Numerisch (8) FORMAT: 00000000
|
||||
var mitgliedsNummer: Int? = null,
|
||||
|
||||
// Alphanumerisch (21) Standard: BLANK
|
||||
var telefonNummer: String? = null,
|
||||
|
||||
// Alphanumerisch (1) Standard: BLANK
|
||||
var kader: String? = null,
|
||||
|
||||
/** Numerisch (4). Letztes Jahr, in dem die Lizenz bezahlt wurde. */
|
||||
var lastPayYear: Int? = null,
|
||||
|
||||
/** Bestimmte Lizenzklasse (z.B. R1, R2, ...). */
|
||||
var lizenzKlasse: ReiterLizenzKlasseE = ReiterLizenzKlasseE.LIZENZFREI,
|
||||
|
||||
// Alphanumerisch (1) WERTE: M=MÄNNLICH, W=WEIBLICH
|
||||
var geschlecht: String? = null,
|
||||
|
||||
// Datum (8) FORMAT: YYYYMMDD
|
||||
@Serializable(with = LocalDateSerializer::class)
|
||||
var geburtsdatum: LocalDate? = null,
|
||||
|
||||
// Alphanumerisch (10) Standard: BLANK
|
||||
var feiId: String? = null,
|
||||
|
||||
// Alphanumerisch (1) Werte: BLANK = nicht auf Sperrliste, S=auf Sperrliste, dort nachsehen!
|
||||
var sperrListe: String? = null,
|
||||
|
||||
// Alphanumerisch (10) Standard: BLANK
|
||||
var lizenzInfo: String? = null,
|
||||
|
||||
var lizenzKlasse: LizenzKlasseE = LizenzKlasseE.LIZENZFREI,
|
||||
// === ZNS.zip LIZENZ01.DAT === ENDE ===
|
||||
|
||||
// Kontakt
|
||||
var imageUrl: String? = null,
|
||||
var email: String? = null,
|
||||
var telefon: String? = null,
|
||||
var website: String? = null,
|
||||
|
||||
// Adresse
|
||||
var strasse: String? = null,
|
||||
var hausnummer: String? = null,
|
||||
var plz: String? = null,
|
||||
var ort: String? = null,
|
||||
var bundesland: String? = null,
|
||||
|
||||
// Status & Verwaltung
|
||||
val istAktiv: Boolean = true,
|
||||
var bemerkungen: String? = null,
|
||||
val datenQuelle: DatenQuelleE = DatenQuelleE.IMPORT_ZNS,
|
||||
|
||||
// Audit
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
val createdAt: Instant = Clock.System.now(),
|
||||
@Serializable(with = InstantSerializer::class)
|
||||
@@ -112,19 +170,19 @@ data class DomReiter(
|
||||
fun hasLizenz(): Boolean = !reiterLizenz.isNullOrBlank()
|
||||
|
||||
/**
|
||||
* Checks if the rider has a license for a specific sparte.
|
||||
* Checks if the rider holds a license for a specific discipline.
|
||||
* Simple logic for now: Any non-blank license field counts.
|
||||
*/
|
||||
fun hasLizenzForSparte(sparte: SparteE): Boolean {
|
||||
// If we have a license class, check if it's applicable for the sparte
|
||||
if (lizenzKlasse == LizenzKlasseE.LIZENZFREI) return false
|
||||
|
||||
fun hasLizenzForSparte(sparte: at.mocode.core.domain.model.SparteE): Boolean {
|
||||
return when (sparte) {
|
||||
SparteE.DRESSUR -> true // Everyone with a license can do dressage (simplified)
|
||||
SparteE.SPRINGEN -> !listOf(LizenzKlasseE.RD1, LizenzKlasseE.RD2, LizenzKlasseE.RD3).contains(lizenzKlasse)
|
||||
else -> true
|
||||
at.mocode.core.domain.model.SparteE.DRESSUR -> !reiterLizenz.isNullOrBlank()
|
||||
at.mocode.core.domain.model.SparteE.SPRINGEN -> !reiterLizenz.isNullOrBlank()
|
||||
at.mocode.core.domain.model.SparteE.FAHREN -> !fahrLizenz.isNullOrBlank()
|
||||
else -> hasLizenz()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates the rider for competition entry.
|
||||
* Returns a list of warning messages (never hard errors – TBA has final say).
|
||||
@@ -146,5 +204,5 @@ data class DomReiter(
|
||||
/**
|
||||
* Creates a copy of this rider with an updated timestamp.
|
||||
*/
|
||||
fun withUpdatedTimestamp(): DomReiter = this.copy(updatedAt = Clock.System.now())
|
||||
fun withUpdatedTimestamp(): Reiter = this.copy(updatedAt = Clock.System.now())
|
||||
}
|
||||
+24
-21
@@ -21,8 +21,7 @@ import kotlin.uuid.Uuid
|
||||
*
|
||||
* @property vereinId Eindeutige interne ID (UUID).
|
||||
* @property vereinsNummer ÖPS-Vereinsnummer aus ZNS (VEREIN01.dat), 4-stellig. Primärschlüssel für ZNS-Datenaustausch.
|
||||
* @property name Offizieller Vereinsname.
|
||||
* @property kurzname Kurzbezeichnung des Vereins (optional).
|
||||
* @property vereinName Offizieller Vereinsname.
|
||||
* @property bundesland Bundesland, in dem der Verein ansässig ist.
|
||||
* @property ort Ort / Stadt des Vereinssitzes.
|
||||
* @property plz Postleitzahl.
|
||||
@@ -30,7 +29,6 @@ import kotlin.uuid.Uuid
|
||||
* @property email Offizielle E-Mail-Adresse des Vereins.
|
||||
* @property telefon Telefonnummer des Vereins.
|
||||
* @property website Website-URL des Vereins.
|
||||
* @property oepsRegionNummer Regionsnummer beim OEPS (Landesverband).
|
||||
* @property istVeranstalter Ob der Verein als Veranstalter von Turnieren zugelassen ist.
|
||||
* @property istAktiv Ob der Verein aktuell aktiv ist.
|
||||
* @property bemerkungen Interne Notizen.
|
||||
@@ -39,35 +37,40 @@ import kotlin.uuid.Uuid
|
||||
* @property updatedAt Letzter Änderungszeitpunkt.
|
||||
*/
|
||||
@Serializable
|
||||
data class DomVerein(
|
||||
data class Verein(
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val vereinId: Uuid = Uuid.random(),
|
||||
|
||||
// Identifikation
|
||||
// Reference to base person
|
||||
@Serializable(with = UuidSerializer::class)
|
||||
val personId: Uuid? = null,
|
||||
|
||||
// === ZNS.zip VEREIN01.DAT === ANFANG ===
|
||||
|
||||
/** Numerisch (4) FORMAT: 0000. Primärschlüssel für ZNS-Datenaustausch. */
|
||||
val vereinsNummer: String,
|
||||
|
||||
// Stammdaten
|
||||
var name: String,
|
||||
var kurzname: String? = null,
|
||||
/** Alphanumerisch (50). Offizieller Vereinsname. */
|
||||
var vereinName: String,
|
||||
|
||||
// Adresse
|
||||
var bundesland: String? = null,
|
||||
var ort: String? = null,
|
||||
var plz: String? = null,
|
||||
var strasse: String? = null,
|
||||
// === ZNS.zip VEREIN01.DAT === ENDE ===
|
||||
|
||||
// Kontakt
|
||||
var imageUrl: String? = null,
|
||||
var email: String? = null,
|
||||
var telefon: String? = null,
|
||||
var website: String? = null,
|
||||
|
||||
// OEPS-Verwaltung
|
||||
var oepsRegionNummer: String? = null,
|
||||
var istVeranstalter: Boolean = false,
|
||||
// Adresse
|
||||
var strasse: String? = null,
|
||||
var hausnummer: String? = null,
|
||||
var plz: String? = null,
|
||||
var ort: String? = null,
|
||||
var bundesland: String? = null,
|
||||
|
||||
// Status & Verwaltung
|
||||
var istAktiv: Boolean = true,
|
||||
var logoUrl: String? = null,
|
||||
var istVeranstalter: Boolean = false,
|
||||
var bemerkungen: String? = null,
|
||||
var datenQuelle: DatenQuelleE = DatenQuelleE.IMPORT_ZNS,
|
||||
|
||||
@@ -80,7 +83,7 @@ data class DomVerein(
|
||||
/**
|
||||
* Gibt den Anzeigenamen zurück – Kurzname bevorzugt, sonst vollständiger Name.
|
||||
*/
|
||||
fun getDisplayName(): String = kurzname ?: name
|
||||
fun getDisplayName(): String = vereinName
|
||||
|
||||
/**
|
||||
* Gibt den vollständigen Anzeigenamen mit Vereinsnummer zurück.
|
||||
@@ -91,13 +94,13 @@ data class DomVerein(
|
||||
* Prüft, ob vollständige Adressdaten vorhanden sind.
|
||||
*/
|
||||
fun hasCompleteAddress(): Boolean =
|
||||
!ort.isNullOrBlank() && !plz.isNullOrBlank() && !strasse.isNullOrBlank()
|
||||
!strasse.isNullOrBlank() && !plz.isNullOrBlank() && !ort.isNullOrBlank()
|
||||
|
||||
/**
|
||||
* Validiert den Verein für den Einsatz als Veranstalter.
|
||||
* Gibt Warnungen zurück (kein harter Fehler – Override-Event möglich).
|
||||
*/
|
||||
fun validateFuerVeranstaltung(): List<String> {
|
||||
fun validateVeranstaltung(): List<String> {
|
||||
val warnings = mutableListOf<String>()
|
||||
|
||||
if (!istAktiv) {
|
||||
@@ -118,5 +121,5 @@ data class DomVerein(
|
||||
/**
|
||||
* Erstellt eine Kopie mit aktualisiertem Zeitstempel.
|
||||
*/
|
||||
fun withUpdatedTimestamp(): DomVerein = this.copy(updatedAt = Clock.System.now())
|
||||
fun withUpdatedTimestamp(): Verein = this.copy(updatedAt = Clock.System.now())
|
||||
}
|
||||
+6
-6
@@ -2,11 +2,11 @@
|
||||
|
||||
package at.mocode.masterdata.domain.repository
|
||||
|
||||
import at.mocode.masterdata.domain.model.DomFunktionaer
|
||||
import at.mocode.masterdata.domain.model.Funktionaer
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Repository-Interface für DomFunktionaer (Funktionär) Domain-Operationen.
|
||||
* Repository-Interface für Funktionaer (Funktionär) Domain-Operationen.
|
||||
*
|
||||
* Definiert den Vertrag für Datenzugriffs-Operationen ohne Abhängigkeit
|
||||
* von konkreten Implementierungsdetails (Datenbank, etc.).
|
||||
@@ -16,22 +16,22 @@ interface FunktionaerRepository {
|
||||
/**
|
||||
* Sucht einen Funktionär anhand seiner eindeutigen ID.
|
||||
*/
|
||||
suspend fun findById(id: Uuid): DomFunktionaer?
|
||||
suspend fun findById(id: Uuid): Funktionaer?
|
||||
|
||||
/**
|
||||
* Sucht einen Funktionär anhand seiner Satz-ID und Satznummer.
|
||||
*/
|
||||
suspend fun findBySatz(satzID: String, satzNummer: Int): DomFunktionaer?
|
||||
suspend fun findBySatz(satzID: String, satzNummer: Int): Funktionaer?
|
||||
|
||||
/**
|
||||
* Gibt alle Funktionäre zurück (paginiert).
|
||||
*/
|
||||
suspend fun findAll(limit: Int = 100, offset: Int = 0): List<DomFunktionaer>
|
||||
suspend fun findAll(limit: Int = 100, offset: Int = 0): List<Funktionaer>
|
||||
|
||||
/**
|
||||
* Speichert einen Funktionär (Insert oder Update).
|
||||
*/
|
||||
suspend fun save(funktionaer: DomFunktionaer): DomFunktionaer
|
||||
suspend fun save(funktionaer: Funktionaer): Funktionaer
|
||||
|
||||
/**
|
||||
* Löscht einen Funktionär anhand seiner ID.
|
||||
|
||||
+23
-23
@@ -3,11 +3,11 @@
|
||||
package at.mocode.masterdata.domain.repository
|
||||
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.masterdata.domain.model.DomPferd
|
||||
import at.mocode.masterdata.domain.model.Pferd
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Repository interface for DomPferd (Horse) domain operations.
|
||||
* Repository interface for Pferd (Horse) domain operations.
|
||||
*
|
||||
* This interface defines the contract for horse data access operations
|
||||
* without depending on specific implementation details (database, etc.).
|
||||
@@ -22,7 +22,7 @@ interface HorseRepository {
|
||||
* @param id The unique identifier of the horse
|
||||
* @return The horse if found, null otherwise
|
||||
*/
|
||||
suspend fun findById(id: Uuid): DomPferd?
|
||||
suspend fun findById(id: Uuid): Pferd?
|
||||
|
||||
/**
|
||||
* Finds a horse by its life number (Lebensnummer).
|
||||
@@ -30,7 +30,7 @@ interface HorseRepository {
|
||||
* @param lebensnummer The life number to search for
|
||||
* @return The horse if found, null otherwise
|
||||
*/
|
||||
suspend fun findByLebensnummer(lebensnummer: String): DomPferd?
|
||||
suspend fun findByLebensnummer(lebensnummer: String): Pferd?
|
||||
|
||||
/**
|
||||
* Finds a horse by its chip number.
|
||||
@@ -38,7 +38,7 @@ interface HorseRepository {
|
||||
* @param chipNummer The chip number to search for
|
||||
* @return The horse if found, null otherwise
|
||||
*/
|
||||
suspend fun findByChipNummer(chipNummer: String): DomPferd?
|
||||
suspend fun findByChipNummer(chipNummer: String): Pferd?
|
||||
|
||||
/**
|
||||
* Finds a horse by its passport number.
|
||||
@@ -46,7 +46,7 @@ interface HorseRepository {
|
||||
* @param passNummer The passport number to search for
|
||||
* @return The horse if found, null otherwise
|
||||
*/
|
||||
suspend fun findByPassNummer(passNummer: String): DomPferd?
|
||||
suspend fun findByPassNummer(passNummer: String): Pferd?
|
||||
|
||||
/**
|
||||
* Finds a horse by its OEPS number.
|
||||
@@ -54,7 +54,7 @@ interface HorseRepository {
|
||||
* @param oepsNummer The OEPS number to search for
|
||||
* @return The horse if found, null otherwise
|
||||
*/
|
||||
suspend fun findByOepsNummer(oepsNummer: String): DomPferd?
|
||||
suspend fun findByOepsNummer(oepsNummer: String): Pferd?
|
||||
|
||||
/**
|
||||
* Finds a horse by its FEI number.
|
||||
@@ -62,7 +62,7 @@ interface HorseRepository {
|
||||
* @param feiNummer The FEI number to search for
|
||||
* @return The horse if found, null otherwise
|
||||
*/
|
||||
suspend fun findByFeiNummer(feiNummer: String): DomPferd?
|
||||
suspend fun findByFeiNummer(feiNummer: String): Pferd?
|
||||
|
||||
/**
|
||||
* Finds horses by name (partial match).
|
||||
@@ -71,7 +71,7 @@ interface HorseRepository {
|
||||
* @param limit Maximum number of results to return
|
||||
* @return List of matching horses
|
||||
*/
|
||||
suspend fun findByName(searchTerm: String, limit: Int = 50): List<DomPferd>
|
||||
suspend fun findByName(searchTerm: String, limit: Int = 50): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds all horses owned by a specific person.
|
||||
@@ -80,7 +80,7 @@ interface HorseRepository {
|
||||
* @param activeOnly Whether to return only active horses
|
||||
* @return List of horses owned by the person
|
||||
*/
|
||||
suspend fun findByOwnerId(ownerId: Uuid, activeOnly: Boolean = true): List<DomPferd>
|
||||
suspend fun findByOwnerId(ownerId: Uuid, activeOnly: Boolean = true): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds all horses for which a person is responsible.
|
||||
@@ -89,7 +89,7 @@ interface HorseRepository {
|
||||
* @param activeOnly Whether to return only active horses
|
||||
* @return List of horses for which the person is responsible
|
||||
*/
|
||||
suspend fun findByResponsiblePersonId(responsiblePersonId: Uuid, activeOnly: Boolean = true): List<DomPferd>
|
||||
suspend fun findByResponsiblePersonId(responsiblePersonId: Uuid, activeOnly: Boolean = true): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds horses by gender.
|
||||
@@ -103,7 +103,7 @@ interface HorseRepository {
|
||||
geschlecht: PferdeGeschlechtE,
|
||||
activeOnly: Boolean = true,
|
||||
limit: Int = 100
|
||||
): List<DomPferd>
|
||||
): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds horses by breed.
|
||||
@@ -113,7 +113,7 @@ interface HorseRepository {
|
||||
* @param limit Maximum number of results to return
|
||||
* @return List of horses of the specified breed
|
||||
*/
|
||||
suspend fun findByRasse(rasse: String, activeOnly: Boolean = true, limit: Int = 100): List<DomPferd>
|
||||
suspend fun findByRasse(rasse: String, activeOnly: Boolean = true, limit: Int = 100): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds horses by birth year.
|
||||
@@ -122,7 +122,7 @@ interface HorseRepository {
|
||||
* @param activeOnly Whether to return only active horses
|
||||
* @return List of horses born in the specified year
|
||||
*/
|
||||
suspend fun findByBirthYear(birthYear: Int, activeOnly: Boolean = true): List<DomPferd>
|
||||
suspend fun findByBirthYear(birthYear: Int, activeOnly: Boolean = true): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds horses by birth year range.
|
||||
@@ -132,7 +132,7 @@ interface HorseRepository {
|
||||
* @param activeOnly Whether to return only active horses
|
||||
* @return List of horses born within the specified year range
|
||||
*/
|
||||
suspend fun findByBirthYearRange(fromYear: Int, toYear: Int, activeOnly: Boolean = true): List<DomPferd>
|
||||
suspend fun findByBirthYearRange(fromYear: Int, toYear: Int, activeOnly: Boolean = true): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds all active horses.
|
||||
@@ -140,7 +140,7 @@ interface HorseRepository {
|
||||
* @param limit Maximum number of results to return
|
||||
* @return List of active horses
|
||||
*/
|
||||
suspend fun findAllActive(limit: Int = 1000): List<DomPferd>
|
||||
suspend fun findAllActive(limit: Int = 1000): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds horses with OEPS registration.
|
||||
@@ -148,7 +148,7 @@ interface HorseRepository {
|
||||
* @param activeOnly Whether to return only active horses
|
||||
* @return List of OEPS registered horses
|
||||
*/
|
||||
suspend fun findOepsRegistered(activeOnly: Boolean = true): List<DomPferd>
|
||||
suspend fun findOepsRegistered(activeOnly: Boolean = true): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds horses with FEI registration.
|
||||
@@ -156,7 +156,7 @@ interface HorseRepository {
|
||||
* @param activeOnly Whether to return only active horses
|
||||
* @return List of FEI registered horses
|
||||
*/
|
||||
suspend fun findFeiRegistered(activeOnly: Boolean = true): List<DomPferd>
|
||||
suspend fun findFeiRegistered(activeOnly: Boolean = true): List<Pferd>
|
||||
|
||||
/**
|
||||
* Saves a horse (create or update).
|
||||
@@ -164,7 +164,7 @@ interface HorseRepository {
|
||||
* @param horse The horse to save
|
||||
* @return The saved horse with updated timestamps
|
||||
*/
|
||||
suspend fun save(horse: DomPferd): DomPferd
|
||||
suspend fun save(horse: Pferd): Pferd
|
||||
|
||||
/**
|
||||
* Deletes a horse by ID.
|
||||
@@ -252,7 +252,7 @@ interface HorseRepository {
|
||||
* @param kopfnummer The head number to search for
|
||||
* @return The list of horses found
|
||||
*/
|
||||
suspend fun findByKopfnummer(kopfnummer: String): List<DomPferd>
|
||||
suspend fun findByKopfnummer(kopfnummer: String): List<Pferd>
|
||||
|
||||
/**
|
||||
* Finds a horse by its ZNS satznummer.
|
||||
@@ -260,17 +260,17 @@ interface HorseRepository {
|
||||
* @param satznummer The ZNS satznummer to search for
|
||||
* @return The horse if found, null otherwise
|
||||
*/
|
||||
suspend fun findBySatznummer(satznummer: String): DomPferd?
|
||||
suspend fun findBySatznummer(satznummer: String): Pferd?
|
||||
|
||||
/**
|
||||
* Speichert ein Pferd basierend auf der ZNS satznummer (Upsert).
|
||||
* Wenn ein Pferd mit der satznummer existiert, wird es aktualisiert, ansonsten neu angelegt.
|
||||
*/
|
||||
suspend fun upsertBySatznummer(horse: DomPferd): DomPferd
|
||||
suspend fun upsertBySatznummer(horse: Pferd): Pferd
|
||||
|
||||
/**
|
||||
* Speichert ein Pferd basierend auf der Lebensnummer (Upsert).
|
||||
* Wenn ein Pferd mit der Lebensnummer existiert, wird es aktualisiert, ansonsten neu angelegt.
|
||||
*/
|
||||
suspend fun upsertByLebensnummer(horse: DomPferd): DomPferd
|
||||
suspend fun upsertByLebensnummer(horse: Pferd): Pferd
|
||||
}
|
||||
|
||||
+7
-7
@@ -2,11 +2,11 @@
|
||||
|
||||
package at.mocode.masterdata.domain.repository
|
||||
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Repository-Interface für DomReiter (Reiter) Domain-Operationen.
|
||||
* Repository-Interface für Reiter (Reiter) Domain-Operationen.
|
||||
*
|
||||
* Definiert den Vertrag für Datenzugriffs-Operationen ohne Abhängigkeit
|
||||
* von konkreten Implementierungsdetails (Datenbank etc.).
|
||||
@@ -16,22 +16,22 @@ interface ReiterRepository {
|
||||
/**
|
||||
* Sucht einen Reiter anhand seiner eindeutigen ID.
|
||||
*/
|
||||
suspend fun findById(id: Uuid): DomReiter?
|
||||
suspend fun findById(id: Uuid): Reiter?
|
||||
|
||||
/**
|
||||
* Sucht einen Reiter anhand seiner Satznummer (OEPS-Mitgliedsnummer).
|
||||
*/
|
||||
suspend fun findBySatznummer(satznummer: String?): DomReiter?
|
||||
suspend fun findBySatznummer(satznummer: String?): Reiter?
|
||||
|
||||
/**
|
||||
* Gibt alle Reiter zurück (paginiert).
|
||||
*/
|
||||
suspend fun findAll(limit: Int = 100, offset: Int = 0): List<DomReiter>
|
||||
suspend fun findAll(limit: Int = 100, offset: Int = 0): List<Reiter>
|
||||
|
||||
/**
|
||||
* Speichert einen Reiter (Insert oder Update).
|
||||
*/
|
||||
suspend fun save(reiter: DomReiter): DomReiter
|
||||
suspend fun save(reiter: Reiter): Reiter
|
||||
|
||||
/**
|
||||
* Löscht einen Reiter anhand seiner ID.
|
||||
@@ -54,5 +54,5 @@ interface ReiterRepository {
|
||||
* Speichert einen Reiter basierend auf der Satznummer (Upsert).
|
||||
* Wenn ein Reiter mit der Satznummer existiert, wird er aktualisiert, ansonsten neu angelegt.
|
||||
*/
|
||||
suspend fun upsertBySatznummer(reiter: DomReiter): DomReiter
|
||||
suspend fun upsertBySatznummer(reiter: Reiter): Reiter
|
||||
}
|
||||
|
||||
+11
-11
@@ -2,11 +2,11 @@
|
||||
|
||||
package at.mocode.masterdata.domain.repository
|
||||
|
||||
import at.mocode.masterdata.domain.model.DomVerein
|
||||
import at.mocode.masterdata.domain.model.Verein
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Repository-Interface für DomVerein (Verein) Domain-Operationen.
|
||||
* Repository-Interface für Verein (Verein) Domain-Operationen.
|
||||
*
|
||||
* Definiert den Vertrag für Datenzugriffs-Operationen ohne Abhängigkeit
|
||||
* von konkreten Implementierungsdetails (Datenbank etc.).
|
||||
@@ -16,42 +16,42 @@ interface VereinRepository {
|
||||
/**
|
||||
* Sucht einen Verein anhand seiner eindeutigen ID.
|
||||
*/
|
||||
suspend fun findById(id: Uuid): DomVerein?
|
||||
suspend fun findById(id: Uuid): Verein?
|
||||
|
||||
/**
|
||||
* Sucht einen Verein anhand seiner OEPS-Vereinsnummer.
|
||||
*/
|
||||
suspend fun findByVereinsNummer(vereinsNummer: String): DomVerein?
|
||||
suspend fun findByVereinsNummer(vereinsNummer: String): Verein?
|
||||
|
||||
/**
|
||||
* Sucht Vereine anhand des Namens (Teilübereinstimmung).
|
||||
*/
|
||||
suspend fun findByName(searchTerm: String, limit: Int = 50): List<DomVerein>
|
||||
suspend fun findByName(searchTerm: String, limit: Int = 50): List<Verein>
|
||||
|
||||
/**
|
||||
* Sucht alle Vereine eines Bundeslandes.
|
||||
*/
|
||||
suspend fun findByBundesland(bundesland: String, activeOnly: Boolean = true): List<DomVerein>
|
||||
suspend fun findByBundesland(bundesland: String, activeOnly: Boolean = true): List<Verein>
|
||||
|
||||
/**
|
||||
* Sucht alle Vereine, die als Veranstalter markiert sind.
|
||||
*/
|
||||
suspend fun findVeranstalter(activeOnly: Boolean = true): List<DomVerein>
|
||||
suspend fun findVeranstalter(activeOnly: Boolean = true): List<Verein>
|
||||
|
||||
/**
|
||||
* Gibt alle aktiven Vereine zurück (paginiert).
|
||||
*/
|
||||
suspend fun findAllActive(limit: Int = 100, offset: Int = 0): List<DomVerein>
|
||||
suspend fun findAllActive(limit: Int = 100, offset: Int = 0): List<Verein>
|
||||
|
||||
/**
|
||||
* Gibt alle Vereine zurück (paginiert).
|
||||
*/
|
||||
suspend fun findAll(limit: Int = 100, offset: Int = 0): List<DomVerein>
|
||||
suspend fun findAll(limit: Int = 100, offset: Int = 0): List<Verein>
|
||||
|
||||
/**
|
||||
* Speichert einen Verein (Insert oder Update).
|
||||
*/
|
||||
suspend fun save(verein: DomVerein): DomVerein
|
||||
suspend fun save(verein: Verein): Verein
|
||||
|
||||
/**
|
||||
* Löscht einen Verein anhand seiner ID.
|
||||
@@ -74,5 +74,5 @@ interface VereinRepository {
|
||||
* Speichert einen Verein basierend auf der Vereinsnummer (Upsert).
|
||||
* Wenn ein Verein mit der Nummer existiert, wird er aktualisiert, ansonsten neu angelegt.
|
||||
*/
|
||||
suspend fun upsertByVereinsNummer(verein: DomVerein): DomVerein
|
||||
suspend fun upsertByVereinsNummer(verein: Verein): Verein
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,7 +1,7 @@
|
||||
package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.masterdata.domain.model.DomPferd
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Pferd
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
|
||||
/**
|
||||
* Service zur Prüfung von Abteilungs-Regeln gemäß ÖTO § 39.
|
||||
@@ -23,8 +23,8 @@ interface AbteilungsRegelService {
|
||||
* @return Die Abteilungsnummer (1, 2, 3), in die der Teilnehmer fällt.
|
||||
*/
|
||||
fun ermittleAbteilungStrukturell(
|
||||
reiter: DomReiter,
|
||||
pferd: DomPferd,
|
||||
reiter: Reiter,
|
||||
pferd: Pferd,
|
||||
turnierklasseCode: String,
|
||||
sparte: at.mocode.core.domain.model.SparteE,
|
||||
istCNeu: Boolean = false,
|
||||
|
||||
+9
-9
@@ -1,9 +1,9 @@
|
||||
package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.DomPferd
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Pferd
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
|
||||
/**
|
||||
* Standard-Implementierung des [AbteilungsRegelService] gemäß ÖTO § 39.
|
||||
@@ -11,8 +11,8 @@ import at.mocode.masterdata.domain.model.DomReiter
|
||||
class AbteilungsRegelServiceImpl : AbteilungsRegelService {
|
||||
|
||||
override fun ermittleAbteilungStrukturell(
|
||||
reiter: DomReiter,
|
||||
pferd: DomPferd,
|
||||
reiter: Reiter,
|
||||
pferd: Pferd,
|
||||
turnierklasseCode: String,
|
||||
sparte: SparteE,
|
||||
istCNeu: Boolean,
|
||||
@@ -24,13 +24,13 @@ class AbteilungsRegelServiceImpl : AbteilungsRegelService {
|
||||
if (istCNeu && sparte == SparteE.SPRINGEN) {
|
||||
if (hoehe != null && hoehe <= 95) {
|
||||
return when (reiter.lizenzKlasse) {
|
||||
LizenzKlasseE.LIZENZFREI -> 1
|
||||
LizenzKlasseE.R1, LizenzKlasseE.RD1 -> 2
|
||||
ReiterLizenzKlasseE.LIZENZFREI -> 1
|
||||
ReiterLizenzKlasseE.R1, ReiterLizenzKlasseE.RD1 -> 2
|
||||
else -> 3 // R2+
|
||||
}
|
||||
} else if (hoehe != null && hoehe >= 100) {
|
||||
return when (reiter.lizenzKlasse) {
|
||||
LizenzKlasseE.R1, LizenzKlasseE.RD1 -> 1
|
||||
ReiterLizenzKlasseE.R1, ReiterLizenzKlasseE.RD1 -> 1
|
||||
else -> 2 // R2+
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ class AbteilungsRegelServiceImpl : AbteilungsRegelService {
|
||||
// Fall 2: Klassen A & L (Standardregelung § 39 Abs. 1)
|
||||
if (turnierklasseCode == "A" || turnierklasseCode == "L") {
|
||||
return when (reiter.lizenzKlasse) {
|
||||
LizenzKlasseE.R1, LizenzKlasseE.RD1 -> 1 // Abt. 1: R1
|
||||
ReiterLizenzKlasseE.R1, ReiterLizenzKlasseE.RD1 -> 1 // Abt. 1: R1
|
||||
else -> 2 // Abt. 2+: R2 und höher
|
||||
}
|
||||
}
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@ package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.AltersklasseDefinition
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import kotlinx.datetime.LocalDate
|
||||
|
||||
/**
|
||||
@@ -30,9 +30,9 @@ interface AltersklasseRechner {
|
||||
* @return Eine Liste der zutreffenden Altersklassen-Definitionen.
|
||||
*/
|
||||
fun ermittleAltersklassen(
|
||||
reiter: DomReiter,
|
||||
referenzJahr: Int,
|
||||
sparte: SparteE? = null,
|
||||
verfügbareDefinitionen: List<AltersklasseDefinition>
|
||||
reiter: Reiter,
|
||||
referenzJahr: Int,
|
||||
sparte: SparteE? = null,
|
||||
verfügbareDefinitionen: List<AltersklasseDefinition>
|
||||
): List<AltersklasseDefinition>
|
||||
}
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@ package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.AltersklasseDefinition
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import kotlinx.datetime.LocalDate
|
||||
|
||||
/**
|
||||
@@ -17,10 +17,10 @@ class AltersklasseRechnerImpl : AltersklasseRechner {
|
||||
}
|
||||
|
||||
override fun ermittleAltersklassen(
|
||||
reiter: DomReiter,
|
||||
referenzJahr: Int,
|
||||
sparte: SparteE?,
|
||||
verfügbareDefinitionen: List<AltersklasseDefinition>
|
||||
reiter: Reiter,
|
||||
referenzJahr: Int,
|
||||
sparte: SparteE?,
|
||||
verfügbareDefinitionen: List<AltersklasseDefinition>
|
||||
): List<AltersklasseDefinition> {
|
||||
val geburtsdatum = reiter.geburtsdatum ?: return emptyList()
|
||||
val alter = berechneOetoAlter(geburtsdatum, referenzJahr)
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.model.LicenseMatrixEntry
|
||||
import at.mocode.masterdata.domain.model.TurnierklasseDefinition
|
||||
|
||||
@@ -21,7 +21,7 @@ interface LicenseMatrixService {
|
||||
* @return true, wenn der Reiter startberechtigt ist, sonst false.
|
||||
*/
|
||||
fun isEligible(
|
||||
reiter: DomReiter,
|
||||
reiter: Reiter,
|
||||
turnierklasse: TurnierklasseDefinition,
|
||||
sparte: SparteE,
|
||||
matrix: List<LicenseMatrixEntry>,
|
||||
@@ -37,7 +37,7 @@ interface LicenseMatrixService {
|
||||
* @return Der Code der maximal erlaubten Turnierklasse oder null, wenn keine Regel gefunden wurde.
|
||||
*/
|
||||
fun getMaxTurnierklasse(
|
||||
reiter: DomReiter,
|
||||
reiter: Reiter,
|
||||
sparte: SparteE,
|
||||
matrix: List<LicenseMatrixEntry>
|
||||
): String?
|
||||
|
||||
+3
-3
@@ -1,7 +1,7 @@
|
||||
package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.model.LicenseMatrixEntry
|
||||
import at.mocode.masterdata.domain.model.TurnierklasseDefinition
|
||||
|
||||
@@ -13,7 +13,7 @@ class LicenseMatrixServiceImpl : LicenseMatrixService {
|
||||
private val classHierarchy = listOf("E", "A", "L", "LM", "M", "S")
|
||||
|
||||
override fun isEligible(
|
||||
reiter: DomReiter,
|
||||
reiter: Reiter,
|
||||
turnierklasse: TurnierklasseDefinition,
|
||||
sparte: SparteE,
|
||||
matrix: List<LicenseMatrixEntry>,
|
||||
@@ -35,7 +35,7 @@ class LicenseMatrixServiceImpl : LicenseMatrixService {
|
||||
}
|
||||
|
||||
override fun getMaxTurnierklasse(
|
||||
reiter: DomReiter,
|
||||
reiter: Reiter,
|
||||
sparte: SparteE,
|
||||
matrix: List<LicenseMatrixEntry>
|
||||
): String? {
|
||||
|
||||
+14
-14
@@ -2,11 +2,11 @@
|
||||
|
||||
package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.DomPferd
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Pferd
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
import kotlin.test.assertFalse
|
||||
@@ -17,24 +17,24 @@ class AbteilungsRegelServiceTest {
|
||||
|
||||
private val service = AbteilungsRegelServiceImpl()
|
||||
|
||||
private val standardPferd = DomPferd(pferdeName = "Testpferd", geschlecht = PferdeGeschlechtE.WALLACH)
|
||||
private val standardPferd = Pferd(pferdeName = "Testpferd", geschlecht = PferdeGeschlechtE.WALLACH)
|
||||
private val dummyPersonId = Uuid.random()
|
||||
|
||||
@Test
|
||||
fun `ermittleAbteilungStrukturell teilt Klassen A und L nach R1`() {
|
||||
val r1Reiter = DomReiter(
|
||||
val r1Reiter = Reiter(
|
||||
personId = dummyPersonId,
|
||||
satznummer = "1",
|
||||
nachname = "R1",
|
||||
vorname = "R1",
|
||||
lizenzKlasse = LizenzKlasseE.R1
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R1
|
||||
)
|
||||
val r2Reiter = DomReiter(
|
||||
val r2Reiter = Reiter(
|
||||
personId = dummyPersonId,
|
||||
satznummer = "2",
|
||||
nachname = "R2",
|
||||
vorname = "R2",
|
||||
lizenzKlasse = LizenzKlasseE.R2
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R2
|
||||
)
|
||||
|
||||
assertEquals(1, service.ermittleAbteilungStrukturell(r1Reiter, standardPferd, "A", SparteE.SPRINGEN))
|
||||
@@ -46,26 +46,26 @@ class AbteilungsRegelServiceTest {
|
||||
|
||||
@Test
|
||||
fun `ermittleAbteilungStrukturell berücksichtigt C-NEU Regeln`() {
|
||||
val lfReiter = DomReiter(
|
||||
val lfReiter = Reiter(
|
||||
personId = dummyPersonId,
|
||||
satznummer = "0",
|
||||
nachname = "LF",
|
||||
vorname = "LF",
|
||||
lizenzKlasse = LizenzKlasseE.LIZENZFREI
|
||||
lizenzKlasse = ReiterLizenzKlasseE.LIZENZFREI
|
||||
)
|
||||
val r1Reiter = DomReiter(
|
||||
val r1Reiter = Reiter(
|
||||
personId = dummyPersonId,
|
||||
satznummer = "1",
|
||||
nachname = "R1",
|
||||
vorname = "R1",
|
||||
lizenzKlasse = LizenzKlasseE.R1
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R1
|
||||
)
|
||||
val r2Reiter = DomReiter(
|
||||
val r2Reiter = Reiter(
|
||||
personId = dummyPersonId,
|
||||
satznummer = "2",
|
||||
nachname = "R2",
|
||||
vorname = "R2",
|
||||
lizenzKlasse = LizenzKlasseE.R2
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R2
|
||||
)
|
||||
|
||||
// Bis 95cm
|
||||
|
||||
+3
-3
@@ -4,7 +4,7 @@ package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.AltersklasseDefinition
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import kotlinx.datetime.LocalDate
|
||||
import kotlin.test.Test
|
||||
import kotlin.test.assertEquals
|
||||
@@ -30,7 +30,7 @@ class AltersklasseRechnerTest {
|
||||
|
||||
@Test
|
||||
fun `ermittleAltersklassen findet passende Definitionen`() {
|
||||
val reiter = DomReiter(
|
||||
val reiter = Reiter(
|
||||
personId = Uuid.random(),
|
||||
satznummer = "123456",
|
||||
nachname = "Mustermann",
|
||||
@@ -73,7 +73,7 @@ class AltersklasseRechnerTest {
|
||||
|
||||
@Test
|
||||
fun `ermittleAltersklassen beruecksichtigt SpartenFilter`() {
|
||||
val reiter = DomReiter(
|
||||
val reiter = Reiter(
|
||||
personId = Uuid.random(),
|
||||
satznummer = "123456",
|
||||
nachname = "Mustermann",
|
||||
|
||||
+9
-9
@@ -2,9 +2,9 @@
|
||||
|
||||
package at.mocode.masterdata.domain.service
|
||||
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.model.LicenseMatrixEntry
|
||||
import at.mocode.masterdata.domain.model.TurnierklasseDefinition
|
||||
import kotlin.test.Test
|
||||
@@ -21,7 +21,7 @@ class LicenseMatrixServiceTest {
|
||||
private val matrix = listOf(
|
||||
LicenseMatrixEntry(
|
||||
sparte = SparteE.SPRINGEN,
|
||||
lizenzKlasse = LizenzKlasseE.R1,
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R1,
|
||||
maxTurnierklasseCode = "L",
|
||||
validFrom = nun,
|
||||
createdAt = nun,
|
||||
@@ -29,7 +29,7 @@ class LicenseMatrixServiceTest {
|
||||
),
|
||||
LicenseMatrixEntry(
|
||||
sparte = SparteE.SPRINGEN,
|
||||
lizenzKlasse = LizenzKlasseE.R2,
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R2,
|
||||
maxTurnierklasseCode = "M",
|
||||
validFrom = nun,
|
||||
createdAt = nun,
|
||||
@@ -37,7 +37,7 @@ class LicenseMatrixServiceTest {
|
||||
),
|
||||
LicenseMatrixEntry(
|
||||
sparte = SparteE.DRESSUR,
|
||||
lizenzKlasse = LizenzKlasseE.RD1,
|
||||
lizenzKlasse = ReiterLizenzKlasseE.RD1,
|
||||
maxTurnierklasseCode = "L",
|
||||
validFrom = nun,
|
||||
createdAt = nun,
|
||||
@@ -90,12 +90,12 @@ class LicenseMatrixServiceTest {
|
||||
|
||||
@Test
|
||||
fun `isEligible erlaubt Starts bis zum Limit`() {
|
||||
val r1Reiter = DomReiter(
|
||||
val r1Reiter = Reiter(
|
||||
personId = Uuid.random(),
|
||||
satznummer = "1",
|
||||
nachname = "R1",
|
||||
vorname = "Reiter",
|
||||
lizenzKlasse = LizenzKlasseE.R1
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R1
|
||||
)
|
||||
|
||||
val klasseA = turnierklassen.find { it.code == "A" }!!
|
||||
@@ -109,12 +109,12 @@ class LicenseMatrixServiceTest {
|
||||
|
||||
@Test
|
||||
fun `isEligible verweigert Start ohne passende Spartenlizenz`() {
|
||||
val rd1Reiter = DomReiter(
|
||||
val rd1Reiter = Reiter(
|
||||
personId = Uuid.random(),
|
||||
satznummer = "2",
|
||||
nachname = "RD1",
|
||||
vorname = "Reiter",
|
||||
lizenzKlasse = LizenzKlasseE.RD1
|
||||
lizenzKlasse = ReiterLizenzKlasseE.RD1
|
||||
)
|
||||
|
||||
val klasseA = turnierklassen.find { it.code == "A" }!!
|
||||
|
||||
+2
-2
@@ -2,7 +2,7 @@
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.core.utils.database.DatabaseFactory
|
||||
import at.mocode.masterdata.domain.model.*
|
||||
@@ -72,7 +72,7 @@ class ExposedRegulationRepository : RegulationRepository {
|
||||
private fun ResultRow.toLicenseMatrixEntry() = LicenseMatrixEntry(
|
||||
licenseId = this[LicenseTable.id],
|
||||
sparte = SparteE.valueOf(this[LicenseTable.sparte]),
|
||||
lizenzKlasse = LizenzKlasseE.valueOf(this[LicenseTable.lizenzKlasse]),
|
||||
lizenzKlasse = ReiterLizenzKlasseE.valueOf(this[LicenseTable.lizenzKlasse]),
|
||||
maxTurnierklasseCode = this[LicenseTable.maxTurnierklasseCode],
|
||||
validFrom = this[LicenseTable.validFrom].toKtInstant(),
|
||||
validTo = this[LicenseTable.validTo]?.toOptionalKtInstant(),
|
||||
|
||||
+1
@@ -2,6 +2,7 @@
|
||||
|
||||
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
|
||||
|
||||
+2
@@ -2,6 +2,8 @@
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
|
||||
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.verein.VereinTable
|
||||
import org.jetbrains.exposed.v1.core.Table
|
||||
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||
|
||||
+26
-24
@@ -1,10 +1,9 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
package at.mocode.masterdata.infrastructure.persistence.funktionaer
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.utils.database.DatabaseFactory
|
||||
import at.mocode.masterdata.domain.model.DomFunktionaer
|
||||
import at.mocode.masterdata.domain.model.Funktionaer
|
||||
import at.mocode.masterdata.domain.repository.FunktionaerRepository
|
||||
import org.jetbrains.exposed.v1.core.ResultRow
|
||||
import org.jetbrains.exposed.v1.core.and
|
||||
@@ -19,24 +18,25 @@ import kotlin.uuid.Uuid
|
||||
/**
|
||||
* Exposed-basierte Implementierung des Funktionaer-Repositorys.
|
||||
*/
|
||||
class ExposedFunktionaerRepository : FunktionaerRepository {
|
||||
class FunktionaerExposedRepository : FunktionaerRepository {
|
||||
|
||||
private fun rowToDomFunktionaer(row: ResultRow, qualifikationen: List<String> = emptyList()): DomFunktionaer {
|
||||
return DomFunktionaer(
|
||||
funktionaerId = row[FunktionaerTable.id],
|
||||
satzID = row[FunktionaerTable.satzID] ?: "X",
|
||||
satzNummer = row[FunktionaerTable.satzNummer] ?: 0,
|
||||
name = row[FunktionaerTable.name],
|
||||
qualifikationen = qualifikationen,
|
||||
istAktiv = row[FunktionaerTable.istAktiv],
|
||||
bemerkungen = row[FunktionaerTable.bemerkungen],
|
||||
datenQuelle = DatenQuelleE.valueOf(row[FunktionaerTable.datenQuelle]),
|
||||
createdAt = row[FunktionaerTable.createdAt],
|
||||
updatedAt = row[FunktionaerTable.updatedAt]
|
||||
private fun rowToDomFunktionaer(row: ResultRow, qualifikationen: List<String> = emptyList()): Funktionaer {
|
||||
return Funktionaer(
|
||||
funktionaerId = row[FunktionaerTable.id],
|
||||
personId = row[FunktionaerTable.personId],
|
||||
satzId = row[FunktionaerTable.satzId] ?: "X",
|
||||
satzNummer = row[FunktionaerTable.satzNummer] ?: 0,
|
||||
name = row[FunktionaerTable.name],
|
||||
qualifikationen = qualifikationen,
|
||||
istAktiv = row[FunktionaerTable.istAktiv],
|
||||
bemerkungen = row[FunktionaerTable.bemerkungen],
|
||||
datenQuelle = DatenQuelleE.valueOf(row[FunktionaerTable.datenQuelle]),
|
||||
createdAt = row[FunktionaerTable.createdAt],
|
||||
updatedAt = row[FunktionaerTable.updatedAt]
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun findById(id: Uuid): DomFunktionaer? = DatabaseFactory.dbQuery {
|
||||
override suspend fun findById(id: Uuid): Funktionaer? = DatabaseFactory.dbQuery {
|
||||
val qualifikationen = FunktionaerQualifikationTable
|
||||
.selectAll().where { FunktionaerQualifikationTable.funktionaerId eq id }
|
||||
.map { it[FunktionaerQualifikationTable.qualifikation] }
|
||||
@@ -46,9 +46,9 @@ class ExposedFunktionaerRepository : FunktionaerRepository {
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findBySatz(satzID: String, satzNummer: Int): DomFunktionaer? = DatabaseFactory.dbQuery {
|
||||
override suspend fun findBySatz(satzID: String, satzNummer: Int): Funktionaer? = DatabaseFactory.dbQuery {
|
||||
val row = FunktionaerTable.selectAll()
|
||||
.where { (FunktionaerTable.satzID eq satzID) and (FunktionaerTable.satzNummer eq satzNummer) }
|
||||
.where { (FunktionaerTable.satzId eq satzID) and (FunktionaerTable.satzNummer eq satzNummer) }
|
||||
.singleOrNull() ?: return@dbQuery null
|
||||
|
||||
val qualifikationen = FunktionaerQualifikationTable
|
||||
@@ -58,7 +58,7 @@ class ExposedFunktionaerRepository : FunktionaerRepository {
|
||||
rowToDomFunktionaer(row, qualifikationen)
|
||||
}
|
||||
|
||||
override suspend fun findAll(limit: Int, offset: Int): List<DomFunktionaer> = DatabaseFactory.dbQuery {
|
||||
override suspend fun findAll(limit: Int, offset: Int): List<Funktionaer> = DatabaseFactory.dbQuery {
|
||||
val funktionaere = FunktionaerTable.selectAll()
|
||||
.limit(limit).offset(offset.toLong())
|
||||
.toList()
|
||||
@@ -73,11 +73,12 @@ class ExposedFunktionaerRepository : FunktionaerRepository {
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun save(funktionaer: DomFunktionaer): DomFunktionaer = DatabaseFactory.dbQuery {
|
||||
override suspend fun save(funktionaer: Funktionaer): Funktionaer = DatabaseFactory.dbQuery {
|
||||
val exists = FunktionaerTable.selectAll().where { FunktionaerTable.id eq funktionaer.funktionaerId }.any()
|
||||
if (exists) {
|
||||
FunktionaerTable.update({ FunktionaerTable.id eq funktionaer.funktionaerId }) {
|
||||
it[satzID] = funktionaer.satzID
|
||||
it[personId] = funktionaer.personId
|
||||
it[satzId] = funktionaer.satzId
|
||||
it[satzNummer] = funktionaer.satzNummer
|
||||
it[name] = funktionaer.name
|
||||
it[istAktiv] = funktionaer.istAktiv
|
||||
@@ -88,7 +89,8 @@ class ExposedFunktionaerRepository : FunktionaerRepository {
|
||||
} else {
|
||||
FunktionaerTable.insert {
|
||||
it[id] = funktionaer.funktionaerId
|
||||
it[satzID] = funktionaer.satzID
|
||||
it[personId] = funktionaer.personId
|
||||
it[satzId] = funktionaer.satzId
|
||||
it[satzNummer] = funktionaer.satzNummer
|
||||
it[name] = funktionaer.name
|
||||
it[istAktiv] = funktionaer.istAktiv
|
||||
@@ -121,7 +123,7 @@ class ExposedFunktionaerRepository : FunktionaerRepository {
|
||||
|
||||
override suspend fun existsBySatz(satzID: String, satzNummer: Int): Boolean = DatabaseFactory.dbQuery {
|
||||
FunktionaerTable.selectAll()
|
||||
.where { (FunktionaerTable.satzID eq satzID) and (FunktionaerTable.satzNummer eq satzNummer) }
|
||||
.where { (FunktionaerTable.satzId eq satzID) and (FunktionaerTable.satzNummer eq satzNummer) }
|
||||
.any()
|
||||
}
|
||||
}
|
||||
+28
-4
@@ -1,10 +1,11 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
package at.mocode.masterdata.infrastructure.persistence.funktionaer
|
||||
|
||||
import org.jetbrains.exposed.v1.core.Table
|
||||
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
|
||||
|
||||
/**
|
||||
@@ -12,19 +13,42 @@ import org.jetbrains.exposed.v1.datetime.timestamp
|
||||
*/
|
||||
object FunktionaerTable : Table("funktionaer") {
|
||||
val id = uuid("funktionaer_id")
|
||||
val satzID = varchar("satz_id", 1).nullable()
|
||||
val personId = uuid("person_id").nullable()
|
||||
|
||||
// === ZNS.zip RICHT01.DAT === ANFANG ===
|
||||
|
||||
val satzId = varchar("satz_id", 1)
|
||||
val satzNummer = integer("satz_nummer").nullable()
|
||||
val name = varchar("name", 200).nullable()
|
||||
|
||||
// === ZNS.zip RICHT01.DAT === ENDE ===
|
||||
|
||||
// Kontakt
|
||||
val imageUrl = varchar("image_url", 255).nullable()
|
||||
val email = varchar("email", 200).nullable()
|
||||
val telefon = varchar("telefon", 50).nullable()
|
||||
val website = varchar("website", 255).nullable()
|
||||
|
||||
// Adresse
|
||||
val strasse = varchar("strasse", 200).nullable()
|
||||
val hausnummer = varchar("hausnummer", 10).nullable()
|
||||
val plz = varchar("plz", 10).nullable()
|
||||
val ort = varchar("ort", 100).nullable()
|
||||
val bundesland = varchar("bundesland", 100).nullable()
|
||||
|
||||
// Status & Verwaltung
|
||||
val istAktiv = bool("ist_aktiv").default(true)
|
||||
val bemerkungen = text("bemerkungen").nullable()
|
||||
val datenQuelle = varchar("daten_quelle", 50)
|
||||
|
||||
// Audit
|
||||
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
||||
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
||||
|
||||
override val primaryKey = PrimaryKey(id)
|
||||
|
||||
init {
|
||||
index("idx_funktionaer_satz", isUnique = true, satzID, satzNummer)
|
||||
index("idx_funktionaer_satz", isUnique = true, satzId, satzNummer)
|
||||
}
|
||||
}
|
||||
|
||||
+37
-36
@@ -1,11 +1,11 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
package at.mocode.masterdata.infrastructure.persistence.pferd
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.core.utils.database.DatabaseFactory
|
||||
import at.mocode.masterdata.domain.model.DomPferd
|
||||
import at.mocode.masterdata.domain.model.Pferd
|
||||
import at.mocode.masterdata.domain.repository.HorseRepository
|
||||
import org.jetbrains.exposed.v1.core.ResultRow
|
||||
import org.jetbrains.exposed.v1.core.eq
|
||||
@@ -14,12 +14,13 @@ 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.Uuid
|
||||
|
||||
class HorseRepositoryImpl : HorseRepository {
|
||||
class HorseExposedRepository : HorseRepository {
|
||||
|
||||
private fun rowToDomPferd(row: ResultRow): DomPferd {
|
||||
return DomPferd(
|
||||
private fun rowToPferd(row: ResultRow): Pferd {
|
||||
return Pferd(
|
||||
pferdId = row[HorseTable.id],
|
||||
kopfnummer = row[HorseTable.kopfnummer],
|
||||
pferdeName = row[HorseTable.pferdeName],
|
||||
@@ -42,43 +43,43 @@ class HorseRepositoryImpl : HorseRepository {
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun findById(id: Uuid): DomPferd? = DatabaseFactory.dbQuery {
|
||||
override suspend fun findById(id: Uuid): Pferd? = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.id eq id }
|
||||
.map(::rowToDomPferd)
|
||||
.map(::rowToPferd)
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByLebensnummer(lebensnummer: String): DomPferd? = DatabaseFactory.dbQuery {
|
||||
override suspend fun findByLebensnummer(lebensnummer: String): Pferd? = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.lebensnummer eq lebensnummer }
|
||||
.map(::rowToDomPferd)
|
||||
.map(::rowToPferd)
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findBySatznummer(satznummer: String): DomPferd? = DatabaseFactory.dbQuery {
|
||||
override suspend fun findBySatznummer(satznummer: String): Pferd? = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.satznummer eq satznummer }
|
||||
.map(::rowToDomPferd)
|
||||
.map(::rowToPferd)
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByKopfnummer(kopfnummer: String): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
override suspend fun findByKopfnummer(kopfnummer: String): List<Pferd> = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.kopfnummer eq kopfnummer }
|
||||
.map(::rowToDomPferd)
|
||||
.map(::rowToPferd)
|
||||
}
|
||||
|
||||
override suspend fun findByName(searchTerm: String, limit: Int): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
override suspend fun findByName(searchTerm: String, limit: Int): List<Pferd> = DatabaseFactory.dbQuery {
|
||||
val pattern = "%$searchTerm%"
|
||||
HorseTable.selectAll().where { HorseTable.pferdeName like pattern }
|
||||
.limit(limit)
|
||||
.map(::rowToDomPferd)
|
||||
.map(::rowToPferd)
|
||||
}
|
||||
|
||||
override suspend fun findAllActive(limit: Int): List<DomPferd> = DatabaseFactory.dbQuery {
|
||||
override suspend fun findAllActive(limit: Int): List<Pferd> = DatabaseFactory.dbQuery {
|
||||
HorseTable.selectAll().where { HorseTable.istAktiv eq true }
|
||||
.limit(limit)
|
||||
.map(::rowToDomPferd)
|
||||
.map(::rowToPferd)
|
||||
}
|
||||
|
||||
override suspend fun save(horse: DomPferd): DomPferd = DatabaseFactory.dbQuery {
|
||||
override suspend fun save(horse: Pferd): Pferd = DatabaseFactory.dbQuery {
|
||||
val exists = HorseTable.selectAll().where { HorseTable.id eq horse.pferdId }.any()
|
||||
if (exists) {
|
||||
HorseTable.update({ HorseTable.id eq horse.pferdId }) {
|
||||
@@ -139,11 +140,11 @@ class HorseRepositoryImpl : HorseRepository {
|
||||
HorseTable.selectAll().where { HorseTable.istAktiv eq true }.count()
|
||||
}
|
||||
|
||||
override suspend fun upsertByLebensnummer(horse: DomPferd): DomPferd = DatabaseFactory.dbQuery {
|
||||
override suspend fun upsertByLebensnummer(horse: Pferd): Pferd = DatabaseFactory.dbQuery {
|
||||
val lebensnummer = horse.lebensnummer ?: return@dbQuery save(horse)
|
||||
|
||||
val existing = HorseTable.selectAll().where { HorseTable.lebensnummer eq lebensnummer }
|
||||
.map(::rowToDomPferd)
|
||||
.map(::rowToPferd)
|
||||
.singleOrNull()
|
||||
|
||||
if (existing != null) {
|
||||
@@ -173,11 +174,11 @@ class HorseRepositoryImpl : HorseRepository {
|
||||
}
|
||||
}
|
||||
|
||||
override suspend fun upsertBySatznummer(horse: DomPferd): DomPferd = DatabaseFactory.dbQuery {
|
||||
override suspend fun upsertBySatznummer(horse: Pferd): Pferd = DatabaseFactory.dbQuery {
|
||||
val satznummer = horse.satznummer ?: return@dbQuery save(horse)
|
||||
|
||||
val existing = HorseTable.selectAll().where { HorseTable.satznummer eq satznummer }
|
||||
.map(::rowToDomPferd)
|
||||
.map(::rowToPferd)
|
||||
.singleOrNull()
|
||||
|
||||
if (existing != null) {
|
||||
@@ -207,28 +208,28 @@ class HorseRepositoryImpl : HorseRepository {
|
||||
}
|
||||
}
|
||||
|
||||
// Not implemented or needed based on current requirements/DomPferd state
|
||||
override suspend fun findByChipNummer(chipNummer: String): DomPferd? = null
|
||||
override suspend fun findByPassNummer(passNummer: String): DomPferd? = null
|
||||
override suspend fun findByOepsNummer(oepsNummer: String): DomPferd? = null
|
||||
override suspend fun findByFeiNummer(feiNummer: String): DomPferd? = null
|
||||
override suspend fun findByOwnerId(ownerId: Uuid, activeOnly: Boolean): List<DomPferd> = emptyList()
|
||||
override suspend fun findByResponsiblePersonId(responsiblePersonId: Uuid, activeOnly: Boolean): List<DomPferd> =
|
||||
// Not implemented or needed based on current requirements/Pferd state
|
||||
override suspend fun findByChipNummer(chipNummer: String): Pferd? = null
|
||||
override suspend fun findByPassNummer(passNummer: String): Pferd? = null
|
||||
override suspend fun findByOepsNummer(oepsNummer: String): Pferd? = null
|
||||
override suspend fun findByFeiNummer(feiNummer: String): Pferd? = null
|
||||
override suspend fun findByOwnerId(ownerId: Uuid, activeOnly: Boolean): List<Pferd> = emptyList()
|
||||
override suspend fun findByResponsiblePersonId(responsiblePersonId: Uuid, activeOnly: Boolean): List<Pferd> =
|
||||
emptyList()
|
||||
|
||||
override suspend fun findByGeschlecht(
|
||||
geschlecht: PferdeGeschlechtE,
|
||||
activeOnly: Boolean,
|
||||
limit: Int
|
||||
): List<DomPferd> = emptyList()
|
||||
): List<Pferd> = emptyList()
|
||||
|
||||
override suspend fun findByRasse(rasse: String, activeOnly: Boolean, limit: Int): List<DomPferd> = emptyList()
|
||||
override suspend fun findByBirthYear(birthYear: Int, activeOnly: Boolean): List<DomPferd> = emptyList()
|
||||
override suspend fun findByBirthYearRange(fromYear: Int, toYear: Int, activeOnly: Boolean): List<DomPferd> =
|
||||
override suspend fun findByRasse(rasse: String, activeOnly: Boolean, limit: Int): List<Pferd> = emptyList()
|
||||
override suspend fun findByBirthYear(birthYear: Int, activeOnly: Boolean): List<Pferd> = emptyList()
|
||||
override suspend fun findByBirthYearRange(fromYear: Int, toYear: Int, activeOnly: Boolean): List<Pferd> =
|
||||
emptyList()
|
||||
|
||||
override suspend fun findOepsRegistered(activeOnly: Boolean): List<DomPferd> = emptyList()
|
||||
override suspend fun findFeiRegistered(activeOnly: Boolean): List<DomPferd> = emptyList()
|
||||
override suspend fun findOepsRegistered(activeOnly: Boolean): List<Pferd> = emptyList()
|
||||
override suspend fun findFeiRegistered(activeOnly: Boolean): List<Pferd> = emptyList()
|
||||
override suspend fun existsByChipNummer(chipNummer: String): Boolean = false
|
||||
override suspend fun existsByPassNummer(passNummer: String): Boolean = false
|
||||
override suspend fun existsByOepsNummer(oepsNummer: String): Boolean = false
|
||||
+12
-2
@@ -1,16 +1,21 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
package at.mocode.masterdata.infrastructure.persistence.pferd
|
||||
|
||||
import org.jetbrains.exposed.v1.core.Table
|
||||
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
|
||||
/**
|
||||
* Exposed-Tabellendefinition für die Pferd-Entität basierend auf PFERDE01.DAT.
|
||||
*/
|
||||
object HorseTable : Table("horse") {
|
||||
val id = uuid("horse_id")
|
||||
val personId = uuid("person_id").nullable()
|
||||
|
||||
// === ZNS.zip PFERDE01.DAT === ANFANG ===
|
||||
|
||||
val kopfnummer = varchar("kopfnummer", 4).nullable().index()
|
||||
val pferdeName = varchar("pferde_name", 200).index()
|
||||
val lebensnummer = varchar("lebensnummer", 50).nullable().index()
|
||||
@@ -25,9 +30,14 @@ object HorseTable : Table("horse") {
|
||||
val feiPass = varchar("fei_pass", 50).nullable()
|
||||
val satznummer = varchar("satznummer", 10).nullable()
|
||||
|
||||
// === ZNS.zip PFERDE01.DAT === ENDE ===
|
||||
|
||||
// Status & Verwaltung
|
||||
val istAktiv = bool("ist_aktiv").default(true)
|
||||
val bemerkungen = text("bemerkungen").nullable()
|
||||
val datenQuelle = varchar("daten_quelle", 50)
|
||||
|
||||
// Audit
|
||||
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
||||
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
||||
|
||||
+14
-13
@@ -1,24 +1,25 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
package at.mocode.masterdata.infrastructure.persistence.reiter
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.utils.database.DatabaseFactory
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.repository.ReiterRepository
|
||||
import org.jetbrains.exposed.v1.core.ResultRow
|
||||
import org.jetbrains.exposed.v1.core.eq
|
||||
import org.jetbrains.exposed.v1.jdbc.*
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Exposed-basierte Implementierung des Reiter-Repositorys.
|
||||
*/
|
||||
class ExposedReiterRepository : ReiterRepository {
|
||||
class ReiterExposedRepository : ReiterRepository {
|
||||
|
||||
private fun rowToDomReiter(row: ResultRow): DomReiter {
|
||||
return DomReiter(
|
||||
private fun rowToDomReiter(row: ResultRow): Reiter {
|
||||
return Reiter(
|
||||
reiterId = row[ReiterTable.id],
|
||||
personId = row[ReiterTable.personId],
|
||||
satznummer = row[ReiterTable.satznummer],
|
||||
@@ -41,7 +42,7 @@ class ExposedReiterRepository : ReiterRepository {
|
||||
feiId = row[ReiterTable.feiId],
|
||||
sperrListe = row[ReiterTable.sperrListe],
|
||||
lizenzInfo = row[ReiterTable.lizenzInfo],
|
||||
lizenzKlasse = LizenzKlasseE.valueOf(row[ReiterTable.lizenzKlasse]),
|
||||
lizenzKlasse = ReiterLizenzKlasseE.valueOf(row[ReiterTable.lizenzKlasse]),
|
||||
istAktiv = row[ReiterTable.istAktiv],
|
||||
bemerkungen = row[ReiterTable.bemerkungen],
|
||||
datenQuelle = DatenQuelleE.valueOf(row[ReiterTable.datenQuelle]),
|
||||
@@ -50,25 +51,25 @@ class ExposedReiterRepository : ReiterRepository {
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun findById(id: Uuid): DomReiter? = DatabaseFactory.dbQuery {
|
||||
override suspend fun findById(id: Uuid): Reiter? = DatabaseFactory.dbQuery {
|
||||
ReiterTable.selectAll().where { ReiterTable.id eq id }
|
||||
.map { rowToDomReiter(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findBySatznummer(satznummer: String?): DomReiter? = DatabaseFactory.dbQuery {
|
||||
override suspend fun findBySatznummer(satznummer: String?): Reiter? = DatabaseFactory.dbQuery {
|
||||
ReiterTable.selectAll().where { ReiterTable.satznummer eq satznummer }
|
||||
.map { row -> rowToDomReiter(row) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findAll(limit: Int, offset: Int): List<DomReiter> = DatabaseFactory.dbQuery {
|
||||
override suspend fun findAll(limit: Int, offset: Int): List<Reiter> = DatabaseFactory.dbQuery {
|
||||
ReiterTable.selectAll()
|
||||
.limit(limit).offset(offset.toLong())
|
||||
.map { row -> rowToDomReiter(row) }
|
||||
}
|
||||
|
||||
override suspend fun save(reiter: DomReiter): DomReiter = DatabaseFactory.dbQuery {
|
||||
override suspend fun save(reiter: Reiter): Reiter = DatabaseFactory.dbQuery {
|
||||
val exists = ReiterTable.selectAll().where { ReiterTable.id eq reiter.reiterId }.any()
|
||||
if (exists) {
|
||||
ReiterTable.update({ ReiterTable.id eq reiter.reiterId }) {
|
||||
@@ -147,7 +148,7 @@ class ExposedReiterRepository : ReiterRepository {
|
||||
ReiterTable.selectAll().where { ReiterTable.satznummer eq satznummer }.any()
|
||||
}
|
||||
|
||||
override suspend fun upsertBySatznummer(reiter: DomReiter): DomReiter = DatabaseFactory.dbQuery {
|
||||
override suspend fun upsertBySatznummer(reiter: Reiter): Reiter = DatabaseFactory.dbQuery {
|
||||
val existing = findBySatznummer(reiter.satznummer)
|
||||
|
||||
if (existing != null) {
|
||||
+25
-5
@@ -1,19 +1,22 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
package at.mocode.masterdata.infrastructure.persistence.reiter
|
||||
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import org.jetbrains.exposed.v1.core.Table
|
||||
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
||||
import org.jetbrains.exposed.v1.datetime.date
|
||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
|
||||
/**
|
||||
* Exposed-Tabellendefinition für die Reiter-Entität.
|
||||
*/
|
||||
object ReiterTable : Table("reiter") {
|
||||
val id = uuid("reiter_id")
|
||||
val personId = uuid("person_id")
|
||||
val personId = uuid("person_id").nullable()
|
||||
|
||||
// === ZNS.zip LITENZ01.DAT === ANFANG ===
|
||||
|
||||
val satznummer = varchar("satznummer", 10).nullable()
|
||||
val nachname = varchar("nachname", 100)
|
||||
val vorname = varchar("vorname", 100)
|
||||
@@ -34,11 +37,28 @@ object ReiterTable : Table("reiter") {
|
||||
val feiId = varchar("fei_id", 20).nullable()
|
||||
val sperrListe = varchar("sperr_liste", 50).nullable()
|
||||
val lizenzInfo = varchar("lizenz_info", 100).nullable()
|
||||
val lizenzKlasse = varchar("lizenz_klasse", 50).default(LizenzKlasseE.LIZENZFREI.name)
|
||||
|
||||
// === ZNS.zip LITENZ01.DAT === ENDE ===
|
||||
|
||||
// Kontakt
|
||||
val imageUrl = varchar("image_url", 255).nullable()
|
||||
val email = varchar("email", 200).nullable()
|
||||
val telefon = varchar("telefon", 50).nullable()
|
||||
val website = varchar("website", 255).nullable()
|
||||
|
||||
// Adresse
|
||||
val strasse = varchar("strasse", 200).nullable()
|
||||
val hausnummer = varchar("hausnummer", 10).nullable()
|
||||
val plz = varchar("plz", 10).nullable()
|
||||
val ort = varchar("ort", 100).nullable()
|
||||
val bundesland = varchar("bundesland", 100).nullable()
|
||||
|
||||
// Status & Verwaltung
|
||||
val istAktiv = bool("ist_aktiv").default(true)
|
||||
val bemerkungen = text("bemerkungen").nullable()
|
||||
val datenQuelle = varchar("daten_quelle", 50)
|
||||
|
||||
// Audit
|
||||
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
||||
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
||||
|
||||
+52
-45
@@ -1,102 +1,113 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
package at.mocode.masterdata.infrastructure.persistence.verein
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.utils.database.DatabaseFactory
|
||||
import at.mocode.masterdata.domain.model.DomVerein
|
||||
import at.mocode.masterdata.domain.model.Verein
|
||||
import at.mocode.masterdata.domain.repository.VereinRepository
|
||||
import org.jetbrains.exposed.v1.core.ResultRow
|
||||
import org.jetbrains.exposed.v1.core.eq
|
||||
import org.jetbrains.exposed.v1.core.like
|
||||
import org.jetbrains.exposed.v1.core.or
|
||||
import org.jetbrains.exposed.v1.jdbc.*
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
/**
|
||||
* Exposed-basierte Implementierung des Verein-Repositorys.
|
||||
*/
|
||||
class ExposedVereinRepository : VereinRepository {
|
||||
class VereinExposedRepository : VereinRepository {
|
||||
|
||||
private fun rowToDomVerein(row: ResultRow): DomVerein {
|
||||
return DomVerein(
|
||||
private fun rowToVereinDomain(row: ResultRow): Verein {
|
||||
return Verein(
|
||||
vereinId = row[VereinTable.id],
|
||||
personId = row[VereinTable.personId],
|
||||
|
||||
// === ZNS.zip VEREIN01.DAT === ANFANG ===
|
||||
vereinsNummer = row[VereinTable.vereinsNummer],
|
||||
name = row[VereinTable.name],
|
||||
kurzname = row[VereinTable.kurzname],
|
||||
bundesland = row[VereinTable.bundesland],
|
||||
ort = row[VereinTable.ort],
|
||||
plz = row[VereinTable.plz],
|
||||
strasse = row[VereinTable.strasse],
|
||||
vereinName = row[VereinTable.vereinName],
|
||||
// === ZNS.zip VEREIN01.DAT === ENDE ===
|
||||
|
||||
// Kontakt
|
||||
imageUrl = row[VereinTable.imageUrl],
|
||||
email = row[VereinTable.email],
|
||||
telefon = row[VereinTable.telefon],
|
||||
website = row[VereinTable.website],
|
||||
oepsRegionNummer = row[VereinTable.oepsRegionNummer],
|
||||
istVeranstalter = row[VereinTable.istVeranstalter],
|
||||
|
||||
// Adresse
|
||||
strasse = row[VereinTable.strasse],
|
||||
hausnummer = row[VereinTable.hausnummer],
|
||||
plz = row[VereinTable.plz],
|
||||
ort = row[VereinTable.ort],
|
||||
bundesland = row[VereinTable.bundesland],
|
||||
|
||||
// Status & Verwaltung
|
||||
istAktiv = row[VereinTable.istAktiv],
|
||||
logoUrl = row[VereinTable.logoUrl],
|
||||
istVeranstalter = row[VereinTable.istVeranstalter],
|
||||
bemerkungen = row[VereinTable.bemerkungen],
|
||||
datenQuelle = DatenQuelleE.valueOf(row[VereinTable.datenQuelle]),
|
||||
|
||||
// Audit
|
||||
createdAt = row[VereinTable.createdAt],
|
||||
updatedAt = row[VereinTable.updatedAt]
|
||||
)
|
||||
}
|
||||
|
||||
override suspend fun findById(id: Uuid): DomVerein? = DatabaseFactory.dbQuery {
|
||||
override suspend fun findById(id: Uuid): Verein? = DatabaseFactory.dbQuery {
|
||||
VereinTable.selectAll().where { VereinTable.id eq id }
|
||||
.map(::rowToDomVerein)
|
||||
.map(::rowToVereinDomain)
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByVereinsNummer(vereinsNummer: String): DomVerein? = DatabaseFactory.dbQuery {
|
||||
override suspend fun findByVereinsNummer(vereinsNummer: String): Verein? = DatabaseFactory.dbQuery {
|
||||
VereinTable.selectAll().where { VereinTable.vereinsNummer eq vereinsNummer }
|
||||
.map(::rowToDomVerein)
|
||||
.map(::rowToVereinDomain)
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByName(searchTerm: String, limit: Int): List<DomVerein> = DatabaseFactory.dbQuery {
|
||||
override suspend fun findByName(searchTerm: String, limit: Int): List<Verein> = DatabaseFactory.dbQuery {
|
||||
val pattern = "%$searchTerm%"
|
||||
VereinTable.selectAll().where { (VereinTable.name like pattern) or (VereinTable.kurzname like pattern) }
|
||||
VereinTable.selectAll().where { VereinTable.vereinName like pattern }
|
||||
.limit(limit)
|
||||
.map(::rowToDomVerein)
|
||||
.map(::rowToVereinDomain)
|
||||
}
|
||||
|
||||
override suspend fun findByBundesland(bundesland: String, activeOnly: Boolean): List<DomVerein> =
|
||||
override suspend fun findByBundesland(bundesland: String, activeOnly: Boolean): List<Verein> =
|
||||
DatabaseFactory.dbQuery {
|
||||
val query = VereinTable.selectAll().where { VereinTable.bundesland eq bundesland }
|
||||
if (activeOnly) {
|
||||
query.andWhere { VereinTable.istAktiv eq true }
|
||||
}
|
||||
query.map(::rowToDomVerein)
|
||||
query.map(::rowToVereinDomain)
|
||||
}
|
||||
|
||||
override suspend fun findVeranstalter(activeOnly: Boolean): List<DomVerein> = DatabaseFactory.dbQuery {
|
||||
override suspend fun findVeranstalter(activeOnly: Boolean): List<Verein> = DatabaseFactory.dbQuery {
|
||||
val query = VereinTable.selectAll().where { VereinTable.istVeranstalter eq true }
|
||||
if (activeOnly) {
|
||||
query.andWhere { VereinTable.istAktiv eq true }
|
||||
}
|
||||
query.map(::rowToDomVerein)
|
||||
query.map(::rowToVereinDomain)
|
||||
}
|
||||
|
||||
override suspend fun findAllActive(limit: Int, offset: Int): List<DomVerein> = DatabaseFactory.dbQuery {
|
||||
override suspend fun findAllActive(limit: Int, offset: Int): List<Verein> = DatabaseFactory.dbQuery {
|
||||
VereinTable.selectAll().where { VereinTable.istAktiv eq true }
|
||||
.limit(limit).offset(offset.toLong())
|
||||
.map(::rowToDomVerein)
|
||||
.map(::rowToVereinDomain)
|
||||
}
|
||||
|
||||
override suspend fun findAll(limit: Int, offset: Int): List<DomVerein> = DatabaseFactory.dbQuery {
|
||||
override suspend fun findAll(limit: Int, offset: Int): List<Verein> = DatabaseFactory.dbQuery {
|
||||
VereinTable.selectAll()
|
||||
.limit(limit).offset(offset.toLong())
|
||||
.map(::rowToDomVerein)
|
||||
.map(::rowToVereinDomain)
|
||||
}
|
||||
|
||||
override suspend fun save(verein: DomVerein): DomVerein = DatabaseFactory.dbQuery {
|
||||
override suspend fun save(verein: Verein): Verein = DatabaseFactory.dbQuery {
|
||||
val exists = VereinTable.selectAll().where { VereinTable.id eq verein.vereinId }.any()
|
||||
if (exists) {
|
||||
VereinTable.update({ VereinTable.id eq verein.vereinId }) {
|
||||
it[vereinsNummer] = verein.vereinsNummer
|
||||
it[name] = verein.name
|
||||
it[kurzname] = verein.kurzname
|
||||
it[vereinName] = verein.vereinName
|
||||
it[bundesland] = verein.bundesland
|
||||
it[ort] = verein.ort
|
||||
it[plz] = verein.plz
|
||||
@@ -104,10 +115,9 @@ class ExposedVereinRepository : VereinRepository {
|
||||
it[email] = verein.email
|
||||
it[telefon] = verein.telefon
|
||||
it[website] = verein.website
|
||||
it[oepsRegionNummer] = verein.oepsRegionNummer
|
||||
it[istVeranstalter] = verein.istVeranstalter
|
||||
it[istAktiv] = verein.istAktiv
|
||||
it[logoUrl] = verein.logoUrl
|
||||
it[imageUrl] = verein.imageUrl
|
||||
it[bemerkungen] = verein.bemerkungen
|
||||
it[datenQuelle] = verein.datenQuelle.name
|
||||
it[updatedAt] = verein.updatedAt
|
||||
@@ -116,9 +126,9 @@ class ExposedVereinRepository : VereinRepository {
|
||||
} else {
|
||||
VereinTable.insert {
|
||||
it[id] = verein.vereinId
|
||||
it[personId] = verein.personId
|
||||
it[vereinsNummer] = verein.vereinsNummer
|
||||
it[name] = verein.name
|
||||
it[kurzname] = verein.kurzname
|
||||
it[vereinName] = verein.vereinName
|
||||
it[bundesland] = verein.bundesland
|
||||
it[ort] = verein.ort
|
||||
it[plz] = verein.plz
|
||||
@@ -126,10 +136,9 @@ class ExposedVereinRepository : VereinRepository {
|
||||
it[email] = verein.email
|
||||
it[telefon] = verein.telefon
|
||||
it[website] = verein.website
|
||||
it[oepsRegionNummer] = verein.oepsRegionNummer
|
||||
it[istVeranstalter] = verein.istVeranstalter
|
||||
it[istAktiv] = verein.istAktiv
|
||||
it[logoUrl] = verein.logoUrl
|
||||
it[imageUrl] = verein.imageUrl
|
||||
it[bemerkungen] = verein.bemerkungen
|
||||
it[datenQuelle] = verein.datenQuelle.name
|
||||
it[createdAt] = verein.createdAt
|
||||
@@ -151,17 +160,16 @@ class ExposedVereinRepository : VereinRepository {
|
||||
VereinTable.selectAll().where { VereinTable.vereinsNummer eq vereinsNummer }.any()
|
||||
}
|
||||
|
||||
override suspend fun upsertByVereinsNummer(verein: DomVerein): DomVerein = DatabaseFactory.dbQuery {
|
||||
override suspend fun upsertByVereinsNummer(verein: Verein): Verein = DatabaseFactory.dbQuery {
|
||||
val existing = VereinTable.selectAll().where { VereinTable.vereinsNummer eq verein.vereinsNummer }
|
||||
.map(::rowToDomVerein)
|
||||
.map(::rowToVereinDomain)
|
||||
.singleOrNull()
|
||||
|
||||
if (existing != null) {
|
||||
val toUpdate = verein.copy(vereinId = existing.vereinId)
|
||||
VereinTable.update({ VereinTable.id eq existing.vereinId }) {
|
||||
it[vereinsNummer] = toUpdate.vereinsNummer
|
||||
it[name] = toUpdate.name
|
||||
it[kurzname] = toUpdate.kurzname
|
||||
it[vereinName] = toUpdate.vereinName
|
||||
it[bundesland] = toUpdate.bundesland
|
||||
it[ort] = toUpdate.ort
|
||||
it[plz] = toUpdate.plz
|
||||
@@ -169,10 +177,9 @@ class ExposedVereinRepository : VereinRepository {
|
||||
it[email] = toUpdate.email
|
||||
it[telefon] = toUpdate.telefon
|
||||
it[website] = toUpdate.website
|
||||
it[oepsRegionNummer] = toUpdate.oepsRegionNummer
|
||||
it[istVeranstalter] = toUpdate.istVeranstalter
|
||||
it[istAktiv] = toUpdate.istAktiv
|
||||
it[logoUrl] = toUpdate.logoUrl
|
||||
it[imageUrl] = toUpdate.imageUrl
|
||||
it[bemerkungen] = toUpdate.bemerkungen
|
||||
it[datenQuelle] = toUpdate.datenQuelle.name
|
||||
it[updatedAt] = toUpdate.updatedAt
|
||||
+26
-11
@@ -1,32 +1,47 @@
|
||||
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
package at.mocode.masterdata.infrastructure.persistence.verein
|
||||
|
||||
import org.jetbrains.exposed.v1.core.Table
|
||||
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
|
||||
import org.jetbrains.exposed.v1.datetime.timestamp
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
|
||||
/**
|
||||
* Exposed-Tabellendefinition für die Verein-Entität.
|
||||
*/
|
||||
object VereinTable : Table("verein") {
|
||||
val id = uuid("verein_id")
|
||||
|
||||
val personId = uuid("person_id").nullable()
|
||||
|
||||
// === ZNS.zip VEREIN01.DAT === ANFANG ===
|
||||
|
||||
val vereinsNummer = varchar("vereins_nummer", 10).uniqueIndex()
|
||||
val name = varchar("name", 200)
|
||||
val kurzname = varchar("kurzname", 100).nullable()
|
||||
val bundesland = varchar("bundesland", 100).nullable()
|
||||
val ort = varchar("ort", 100).nullable()
|
||||
val plz = varchar("plz", 10).nullable()
|
||||
val strasse = varchar("strasse", 200).nullable()
|
||||
val vereinName = varchar("verein_name", 200)
|
||||
|
||||
// === ZNS.zip VEREIN01.DAT === ENDE ===
|
||||
|
||||
// Kontakt
|
||||
val imageUrl = varchar("image_url", 255).nullable()
|
||||
val email = varchar("email", 200).nullable()
|
||||
val telefon = varchar("telefon", 50).nullable()
|
||||
val website = varchar("website", 255).nullable()
|
||||
val oepsRegionNummer = varchar("oeps_region_nummer", 10).nullable()
|
||||
val istVeranstalter = bool("ist_veranstalter").default(false)
|
||||
|
||||
// Adresse
|
||||
val strasse = varchar("strasse", 200).nullable()
|
||||
val hausnummer = varchar("hausnummer", 10).nullable()
|
||||
val plz = varchar("plz", 10).nullable()
|
||||
val ort = varchar("ort", 100).nullable()
|
||||
val bundesland = varchar("bundesland", 100).nullable()
|
||||
|
||||
// Status & Verwaltung
|
||||
val istAktiv = bool("ist_aktiv").default(true)
|
||||
val logoUrl = varchar("logo_url", 255).nullable()
|
||||
val istVeranstalter = bool("ist_veranstalter").default(false)
|
||||
val bemerkungen = text("bemerkungen").nullable()
|
||||
val datenQuelle = varchar("daten_quelle", 50)
|
||||
|
||||
// Audit
|
||||
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
|
||||
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
|
||||
|
||||
+5
-5
@@ -2,7 +2,7 @@
|
||||
|
||||
package at.mocode.masterdata.infrastructure.persistence
|
||||
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.model.SparteE
|
||||
import at.mocode.masterdata.domain.model.LicenseMatrixEntry
|
||||
import at.mocode.masterdata.domain.model.TurnierklasseDefinition
|
||||
@@ -77,7 +77,7 @@ class RegulationSeedVerificationTest {
|
||||
val oetoMatrix = listOf(
|
||||
LicenseMatrixEntry(
|
||||
sparte = SparteE.SPRINGEN,
|
||||
lizenzKlasse = LizenzKlasseE.R1,
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R1,
|
||||
maxTurnierklasseCode = "L",
|
||||
validFrom = now,
|
||||
createdAt = now,
|
||||
@@ -85,7 +85,7 @@ class RegulationSeedVerificationTest {
|
||||
),
|
||||
LicenseMatrixEntry(
|
||||
sparte = SparteE.SPRINGEN,
|
||||
lizenzKlasse = LizenzKlasseE.R2,
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R2,
|
||||
maxTurnierklasseCode = "M",
|
||||
validFrom = now,
|
||||
createdAt = now,
|
||||
@@ -93,12 +93,12 @@ class RegulationSeedVerificationTest {
|
||||
)
|
||||
)
|
||||
|
||||
val r1Reiter = at.mocode.masterdata.domain.model.DomReiter(
|
||||
val r1Reiter = at.mocode.masterdata.domain.model.Reiter(
|
||||
personId = Uuid.random(),
|
||||
satznummer = "123456",
|
||||
nachname = "Müller",
|
||||
vorname = "Hans",
|
||||
lizenzKlasse = LizenzKlasseE.R1
|
||||
lizenzKlasse = ReiterLizenzKlasseE.R1
|
||||
)
|
||||
|
||||
val klasseL = TurnierklasseDefinition(
|
||||
|
||||
+8
-4
@@ -4,6 +4,10 @@ import at.mocode.masterdata.api.rest.*
|
||||
import at.mocode.masterdata.application.usecase.*
|
||||
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 org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
import org.springframework.context.annotation.Profile
|
||||
@@ -40,22 +44,22 @@ class MasterdataConfiguration {
|
||||
|
||||
@Bean
|
||||
fun reiterRepository(): ReiterRepository {
|
||||
return ExposedReiterRepository()
|
||||
return ReiterExposedRepository()
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun vereinRepository(): VereinRepository {
|
||||
return ExposedVereinRepository()
|
||||
return VereinExposedRepository()
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun horseRepository(): HorseRepository {
|
||||
return HorseRepositoryImpl()
|
||||
return HorseExposedRepository()
|
||||
}
|
||||
|
||||
@Bean
|
||||
fun funktionaerRepository(): FunktionaerRepository {
|
||||
return ExposedFunktionaerRepository()
|
||||
return FunktionaerExposedRepository()
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
||||
+4
@@ -2,6 +2,10 @@ package at.mocode.masterdata.service.config
|
||||
|
||||
|
||||
import at.mocode.masterdata.infrastructure.persistence.*
|
||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.pferd.HorseTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.verein.VereinTable
|
||||
import jakarta.annotation.PostConstruct
|
||||
import jakarta.annotation.PreDestroy
|
||||
import org.jetbrains.exposed.v1.jdbc.SchemaUtils
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
-- V008: Seed OETO 2026 Data (Turnierklassen, Lizenz-Matrix, Altersklassen)
|
||||
-- Basierend auf ÖTO 2026
|
||||
-- Lizenz-Keys entsprechen LizenzKlasseE-Enum (core-domain): LIZENZFREI, R1, R2, R3, R4, RD1, RD2, RD3
|
||||
-- Lizenz-Keys entsprechen ReiterLizenzKlasseE-Enum (core-domain): LIZENZFREI, R1, R2, R3, R4, RD1, RD2, RD3
|
||||
-- HINWEIS: RD4 existiert NICHT im Enum – nur RD1/RD2/RD3 sind gültige Dressur-Lizenzen (ÖTO 2026)
|
||||
|
||||
-- 1. Turnierklassen (Springen & Dressur)
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
-- V009: Regulation-as-Data – Höhen-Lizenz-Matrix (Springen) & Mindestalter-Pferd-Matrix
|
||||
-- Basierend auf ÖTO 2026 (§ 231 Springen, § 103 Dressur) und FEI GR Art. 136
|
||||
-- Lizenz-Keys entsprechen LizenzKlasseE-Enum (core-domain): LIZENZFREI, R1, R2, R3, R4, RD1, RD2, RD3
|
||||
-- Lizenz-Keys entsprechen ReiterLizenzKlasseE-Enum (core-domain): LIZENZFREI, R1, R2, R3, R4, RD1, RD2, RD3
|
||||
-- Status: DRAFT – wird auf STABLE angehoben nach Fachfreigabe durch ÖTO-Fachreferat
|
||||
|
||||
-- ─────────────────────────────────────────────────────────────────────────────
|
||||
|
||||
+8
-5
@@ -1,7 +1,10 @@
|
||||
package at.mocode.zns.import.service.config
|
||||
|
||||
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 org.springframework.context.annotation.Bean
|
||||
import org.springframework.context.annotation.Configuration
|
||||
|
||||
@@ -9,14 +12,14 @@ import org.springframework.context.annotation.Configuration
|
||||
class RepositoryConfiguration {
|
||||
|
||||
@Bean
|
||||
fun vereinRepository(): VereinRepository = ExposedVereinRepository()
|
||||
fun vereinRepository(): VereinRepository = VereinExposedRepository()
|
||||
|
||||
@Bean
|
||||
fun reiterRepository(): ReiterRepository = ExposedReiterRepository()
|
||||
fun reiterRepository(): ReiterRepository = ReiterExposedRepository()
|
||||
|
||||
@Bean
|
||||
fun horseRepository(): HorseRepository = HorseRepositoryImpl()
|
||||
fun horseRepository(): HorseRepository = HorseExposedRepository()
|
||||
|
||||
@Bean
|
||||
fun funktionaerRepository(): FunktionaerRepository = ExposedFunktionaerRepository()
|
||||
fun funktionaerRepository(): FunktionaerRepository = FunktionaerExposedRepository()
|
||||
}
|
||||
|
||||
+4
-4
@@ -1,9 +1,9 @@
|
||||
package at.mocode.zns.import.service.config
|
||||
|
||||
import at.mocode.masterdata.infrastructure.persistence.FunktionaerTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.HorseTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.ReiterTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.VereinTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.funktionaer.FunktionaerTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.pferd.HorseTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.reiter.ReiterTable
|
||||
import at.mocode.masterdata.infrastructure.persistence.verein.VereinTable
|
||||
import jakarta.annotation.PostConstruct
|
||||
import org.jetbrains.exposed.v1.jdbc.Database
|
||||
import org.jetbrains.exposed.v1.jdbc.transactions.transaction
|
||||
|
||||
@@ -159,7 +159,7 @@ enum class VeranstaltungsTypE {
|
||||
* Lizenzklasse eines Reiters gemäß ÖTO Teilnahmeberechtigung.
|
||||
*/
|
||||
@Serializable
|
||||
enum class LizenzKlasseE {
|
||||
enum class ReiterLizenzKlasseE {
|
||||
/** Lizenzfrei – keine Lizenz erforderlich */
|
||||
LIZENZFREI,
|
||||
|
||||
@@ -174,6 +174,7 @@ enum class LizenzKlasseE {
|
||||
|
||||
/** Reiter-Lizenz Klasse 4 */
|
||||
R4,
|
||||
|
||||
/** Dressur-Reiter Klasse 1 */
|
||||
RD1,
|
||||
|
||||
@@ -183,21 +184,35 @@ enum class LizenzKlasseE {
|
||||
/** Dressur-Reiter Klasse 3 */
|
||||
RD3,
|
||||
|
||||
/** Jugend/Nachwuchs */
|
||||
JN,
|
||||
}
|
||||
|
||||
/** Junioren */
|
||||
/**
|
||||
* Altersklasse eines Reiters gemäß ÖTO Teilnahmeberechtigung.
|
||||
*/
|
||||
@Serializable
|
||||
enum class ReiterAltersKlasseE {
|
||||
|
||||
// JUGEND/JUNIOR/U25
|
||||
|
||||
/** Jugend */
|
||||
JG,
|
||||
|
||||
/** Young Rider */
|
||||
YR
|
||||
/** Junioren */
|
||||
JR,
|
||||
|
||||
/** Junge-Reiter */
|
||||
Y,
|
||||
|
||||
/** U25 */
|
||||
U25,
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Status einer Nennung im registration-context.
|
||||
*/
|
||||
@Serializable
|
||||
enum class NennungsStatusE {
|
||||
enum class NennStatusE {
|
||||
/** Nennung eingegangen, noch nicht bestätigt */
|
||||
EINGEGANGEN,
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
package at.mocode.zns.parser
|
||||
|
||||
import at.mocode.core.domain.model.DatenQuelleE
|
||||
import at.mocode.core.domain.model.LizenzKlasseE
|
||||
import at.mocode.core.domain.model.ReiterLizenzKlasseE
|
||||
import at.mocode.core.domain.model.PferdeGeschlechtE
|
||||
import at.mocode.core.utils.parser.FixedWidthLineReader
|
||||
import at.mocode.masterdata.domain.model.DomFunktionaer
|
||||
import at.mocode.masterdata.domain.model.DomPferd
|
||||
import at.mocode.masterdata.domain.model.DomReiter
|
||||
import at.mocode.masterdata.domain.model.DomVerein
|
||||
import at.mocode.masterdata.domain.model.Funktionaer
|
||||
import at.mocode.masterdata.domain.model.Pferd
|
||||
import at.mocode.masterdata.domain.model.Reiter
|
||||
import at.mocode.masterdata.domain.model.Verein
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
@@ -23,7 +23,7 @@ object ZnsLegacyParsers {
|
||||
/**
|
||||
* Parses a line from VEREIN01.DAT.
|
||||
*/
|
||||
fun parseVerein(line: String): DomVerein? {
|
||||
fun parseVerein(line: String): Verein? {
|
||||
if (line.isBlank() || line.length < 5) return null
|
||||
|
||||
val reader = FixedWidthLineReader(line)
|
||||
@@ -33,9 +33,9 @@ object ZnsLegacyParsers {
|
||||
|
||||
if (vereinsNummer.isBlank() || vereinsName.isBlank()) return null
|
||||
|
||||
return DomVerein(
|
||||
return Verein(
|
||||
vereinsNummer = vereinsNummer,
|
||||
name = vereinsName,
|
||||
vereinName = vereinsName,
|
||||
datenQuelle = DatenQuelleE.IMPORT_ZNS
|
||||
)
|
||||
}
|
||||
@@ -43,7 +43,7 @@ object ZnsLegacyParsers {
|
||||
/**
|
||||
* Parses a line from LIZENZ01.DAT.
|
||||
*/
|
||||
fun parseLizenz(line: String): DomReiter? {
|
||||
fun parseLizenz(line: String): Reiter? {
|
||||
if (line.isBlank() || line.length < 57) return null
|
||||
|
||||
val reader = FixedWidthLineReader(line)
|
||||
@@ -79,8 +79,9 @@ object ZnsLegacyParsers {
|
||||
val feiId = reader.getString(190, 8)
|
||||
val sperrListe = reader.getString(198, 1)
|
||||
val lizenzInfo = reader.getString(201, 10)
|
||||
val lizenzKlasse = mapLizenz(reiterLizenz)
|
||||
|
||||
return DomReiter(
|
||||
return Reiter(
|
||||
personId = Uuid.random(),
|
||||
satznummer = satznummer,
|
||||
nachname = nachname,
|
||||
@@ -102,7 +103,7 @@ object ZnsLegacyParsers {
|
||||
feiId = feiId.ifBlank { null },
|
||||
sperrListe = sperrListe.ifBlank { null },
|
||||
lizenzInfo = lizenzInfo.ifBlank { null },
|
||||
lizenzKlasse = mapLizenz(reiterLizenz),
|
||||
lizenzKlasse = lizenzKlasse,
|
||||
datenQuelle = DatenQuelleE.IMPORT_ZNS
|
||||
)
|
||||
}
|
||||
@@ -110,12 +111,16 @@ object ZnsLegacyParsers {
|
||||
/**
|
||||
* Parses a line from PFERDE01.DAT.
|
||||
*/
|
||||
fun parsePferd(line: String): DomPferd? {
|
||||
if (line.isBlank() || line.trim().length < 40) return null
|
||||
fun parsePferd(line: String): Pferd? {
|
||||
if (line.isBlank() || line.trim().length < 4) return null
|
||||
|
||||
val reader = FixedWidthLineReader(line)
|
||||
val kopfnummer = reader.getString(1, 4)
|
||||
val name = reader.getString(5, 30)
|
||||
|
||||
// We need at least a name to identify a horse record
|
||||
if (name.isBlank()) return null
|
||||
|
||||
val lebensnummer = reader.getString(35, 9)
|
||||
val geschlechtChar = reader.getString(44, 1)
|
||||
val geschlecht = mapGeschlecht(geschlechtChar)
|
||||
@@ -128,16 +133,15 @@ object ZnsLegacyParsers {
|
||||
val vaterName = reader.getString(162, 30)
|
||||
val feiPass = reader.getString(192, 10)
|
||||
val satznummer = reader.getString(202, 10)
|
||||
// Some lines might not have a satznummer, but we need at least a name to identify it
|
||||
if (satznummer.isBlank() && name.isBlank()) return null
|
||||
|
||||
return DomPferd(
|
||||
return Pferd(
|
||||
personId = Uuid.random(),
|
||||
pferdeName = name,
|
||||
geschlecht = geschlecht,
|
||||
geburtsjahr = geburtsjahr,
|
||||
lebensnummer = lebensnummer.ifBlank { null },
|
||||
kopfnummer = kopfnummer.ifBlank { null },
|
||||
satznummer = satznummer,
|
||||
satznummer = satznummer.ifBlank { null },
|
||||
farbe = farbe.ifBlank { null },
|
||||
abstammung = abstammung.ifBlank { null },
|
||||
vereinNummer = vereinNummer,
|
||||
@@ -152,7 +156,7 @@ object ZnsLegacyParsers {
|
||||
/**
|
||||
* Parses a line from RICHT01.DAT (Richter oder Parcoursbauer).
|
||||
*/
|
||||
fun parseFunktionaer(line: String): DomFunktionaer? {
|
||||
fun parseFunktionaer(line: String): Funktionaer? {
|
||||
if (line.isBlank() || line.length < 8) return null
|
||||
|
||||
val reader = FixedWidthLineReader(line)
|
||||
@@ -171,8 +175,9 @@ object ZnsLegacyParsers {
|
||||
.map { it.trim() }
|
||||
.filter { it.isNotBlank() }
|
||||
|
||||
return DomFunktionaer(
|
||||
satzID = satzID,
|
||||
return Funktionaer(
|
||||
personId = null,
|
||||
satzId = satzID,
|
||||
satzNummer = satzNummer,
|
||||
name = name.ifBlank { null },
|
||||
qualifikationen = qualifikationen,
|
||||
@@ -180,18 +185,15 @@ object ZnsLegacyParsers {
|
||||
)
|
||||
}
|
||||
|
||||
private fun mapLizenz(lizenz: String): LizenzKlasseE {
|
||||
private fun mapLizenz(lizenz: String): ReiterLizenzKlasseE {
|
||||
return when (lizenz.uppercase()) {
|
||||
"R1" -> LizenzKlasseE.R1
|
||||
"R2" -> LizenzKlasseE.R2
|
||||
"R3" -> LizenzKlasseE.R3
|
||||
"RD1" -> LizenzKlasseE.RD1
|
||||
"RD2" -> LizenzKlasseE.RD2
|
||||
"RD3" -> LizenzKlasseE.RD3
|
||||
"JN" -> LizenzKlasseE.JN
|
||||
"JG" -> LizenzKlasseE.JG
|
||||
"YR" -> LizenzKlasseE.YR
|
||||
else -> LizenzKlasseE.LIZENZFREI
|
||||
"R1" -> ReiterLizenzKlasseE.R1
|
||||
"R2" -> ReiterLizenzKlasseE.R2
|
||||
"R3" -> ReiterLizenzKlasseE.R3
|
||||
"RD1" -> ReiterLizenzKlasseE.RD1
|
||||
"RD2" -> ReiterLizenzKlasseE.RD2
|
||||
"RD3" -> ReiterLizenzKlasseE.RD3
|
||||
else -> ReiterLizenzKlasseE.LIZENZFREI
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ class ZnsLegacyParsersTest {
|
||||
|
||||
assertNotNull(result)
|
||||
assertEquals("1234", result.vereinsNummer)
|
||||
assertEquals("Reitverein Test", result.name)
|
||||
assertEquals("Reitverein Test", result.vereinName)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -82,7 +82,7 @@ class ZnsLegacyParsersTest {
|
||||
val result = ZnsLegacyParsers.parseFunktionaer(line)
|
||||
|
||||
assertNotNull(result)
|
||||
assertEquals("X", result.satzID)
|
||||
assertEquals("X", result.satzId)
|
||||
assertEquals(10128, result.satzNummer)
|
||||
assertEquals("Zitterbart Rainer", result.name)
|
||||
assertEquals(listOf("PI-A"), result.qualifikationen)
|
||||
@@ -94,7 +94,7 @@ class ZnsLegacyParsersTest {
|
||||
val line1 = "X139552Mc Mullen Elizabeth DIOR"
|
||||
val result1 = ZnsLegacyParsers.parseFunktionaer(line1)
|
||||
assertNotNull(result1)
|
||||
assertEquals("X", result1.satzID)
|
||||
assertEquals("X", result1.satzId)
|
||||
assertEquals(139552, result1.satzNummer)
|
||||
assertEquals("Mc Mullen Elizabeth", result1.name)
|
||||
assertEquals(listOf("DIOR"), result1.qualifikationen)
|
||||
@@ -111,10 +111,28 @@ class ZnsLegacyParsersTest {
|
||||
val line3 = "Y002211Salusek Andreas Christian P3,PL2"
|
||||
val result3 = ZnsLegacyParsers.parseFunktionaer(line3)
|
||||
assertNotNull(result3)
|
||||
assertEquals("Y", result3.satzID)
|
||||
assertEquals("Y", result3.satzId)
|
||||
assertEquals(2211, result3.satzNummer)
|
||||
assertEquals("Salusek Andreas Christian", result3.name)
|
||||
assertEquals(listOf("P3", "PL2"), result3.qualifikationen)
|
||||
|
||||
// X001061Kager Franz DPF,DSGP,GAR-SP,GAR-VS,SPF
|
||||
val line4 = "X001061Kager Franz DPF,DSGP,GAR-SP,GAR-VS,SPF"
|
||||
val result4 = ZnsLegacyParsers.parseFunktionaer(line4)
|
||||
assertNotNull(result4)
|
||||
assertEquals("X", result4.satzId)
|
||||
assertEquals(1061, result4.satzNummer)
|
||||
assertEquals("Kager Franz", result4.name)
|
||||
assertEquals(listOf("DPF", "DSGP", "GAR-SP", "GAR-VS", "SPF"), result4.qualifikationen)
|
||||
|
||||
// X001112Keiblinger Brigitta DPF,DSGP,SPF,SS,VS,VSILEV1"
|
||||
val line5 = "X001112Keiblinger Brigitta DPF,DSGP,SPF,SS,VS,VSILEV1"
|
||||
val result5 = ZnsLegacyParsers.parseFunktionaer(line5)
|
||||
assertNotNull(result5)
|
||||
assertEquals("X", result5.satzId)
|
||||
assertEquals(1112, result5.satzNummer)
|
||||
assertEquals("Keiblinger Brigitta", result5.name)
|
||||
assertEquals(listOf("DPF", "DSGP", "SPF", "SS", "VS", "VSILEV1"), result5.qualifikationen)
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -145,6 +163,20 @@ class ZnsLegacyParsersTest {
|
||||
assertEquals("5637401268", result.satznummer)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `parsePferd should extract shortened PFERDE01 correctly`() {
|
||||
// A line that ends after the name
|
||||
val line = "1234Fuchur"
|
||||
val result = ZnsLegacyParsers.parsePferd(line)
|
||||
|
||||
assertNotNull(result)
|
||||
assertEquals("1234", result.kopfnummer)
|
||||
assertEquals("Fuchur", result.pferdeName)
|
||||
assertEquals(null, result.satznummer)
|
||||
assertEquals(null, result.lebensnummer)
|
||||
assertEquals(PferdeGeschlechtE.UNBEKANNT, result.geschlecht)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `parseLizenz should extract real LIZENZ01 correctly for Ebner Sarah`() {
|
||||
// Real example from user:
|
||||
|
||||
@@ -23,7 +23,7 @@ Vollständige Self-Hosted Infrastruktur (Gitea, Pangolin, Zora). Datensouveräni
|
||||
* **CI/CD:** ✅ Gitea Actions mit ARM64-Runner (VM 102) aktiv. Docker-Publish Pipeline grün.
|
||||
* **Code-Basis:** ✅ Backend (Java 25 / Spring Boot / Kotlin), Frontend (KMP/Compose Desktop).
|
||||
* **Domain-Design:** ✅ 6 Bounded Contexts (SCS-Architektur) definiert. Ubiquitous Language erstellt.
|
||||
* **Domain-Modelle:** ✅ `DomReiter`, `DomNennung`, `DomNennungsTransfer`, `DomPferd`, `DomFunktionaer`, `DomVerein`,
|
||||
* **Domain-Modelle:** ✅ `Reiter`, `DomNennung`, `DomNennungsTransfer`, `Pferd`, `Funktionaer`, `Verein`,
|
||||
`DomBewerb`, `DomAbteilung`, `DomStartliste`, `DomVeranstaltung`, `DomTurnier`, `DomAusschreibung` implementiert.
|
||||
Enums ÖTO-konform.
|
||||
* **Dokumentation:** ✅ Konsolidiert. ÖTO-Regelwerk-Referenzen (Abteilungs-Schwellenwerte) dokumentiert.
|
||||
@@ -124,7 +124,7 @@ und über definierte Schnittstellen kommunizieren.
|
||||
|
||||
#### 👷 Agent: Backend Developer
|
||||
|
||||
* [x] **`actor-context`:** Domain-Modelle für `DomPferd`, `DomFunktionaer`, `DomVerein` implementiert.
|
||||
* [x] **`actor-context`:** Domain-Modelle für `Pferd`, `Funktionaer`, `Verein` implementiert.
|
||||
* [x] **`registration-context`:** `DomBewerb`, `DomAbteilung`, `DomStartliste` implementiert.
|
||||
* [x] **`event-management-context`:** `DomVeranstaltung`, `DomTurnier`, `DomAusschreibung` implementiert.
|
||||
* [x] **Persistenz:** Repository-Interfaces und erste DB-Migrationen (Flyway/Liquibase).
|
||||
|
||||
@@ -7,9 +7,10 @@ last_update: 2026-03-25
|
||||
|
||||
# Roadmap: ZNS-Importer (MVP)
|
||||
|
||||
🧹 **[Curator]** | 25. März 2026
|
||||
10. **🏗️ [Lead Architect]** | 5. April 2026
|
||||
|
||||
**Kontext:**
|
||||
Der ZNS-Importer wurde für die Verarbeitung der Datei `RICHT01.dat` optimiert. Es wurde klargestellt, dass Richter (SatzID 'X') und Parcoursbauer (SatzID 'Y') gemeinsam in dieser Datei geliefert werden. Eine separate `PARCO01.dat` existiert nicht.
|
||||
Um den `registration-context` und `actor-context` unter realistischen Bedingungen testen zu können, benötigen wir echte
|
||||
Stammdaten (Reiter, Pferde, Vereine, Funktionäre). Diese Daten werden vom ÖPS (Österreichischer Pferdesportverband) in
|
||||
Form einer `ZNS.zip` bereitgestellt.
|
||||
@@ -29,7 +30,7 @@ gesteuert wird und die Daten persistent im Backend (`actor-context`) ablegt.
|
||||
1. `VEREIN01.dat` (Vereine)
|
||||
2. `LIZENZ01.dat` (Reiter/Lizenzen)
|
||||
3. `PFERDE01.dat` (Pferde - benötigt Vereins-ID)
|
||||
4. `RICHT01.dat` (Richter/Parcoursbauer)
|
||||
4. `RICHT01.dat` (Richter & Parcoursbauer kombiniert in einer Datei)
|
||||
|
||||
---
|
||||
|
||||
@@ -50,7 +51,7 @@ gesteuert wird und die Daten persistent im Backend (`actor-context`) ablegt.
|
||||
* ZIP-Entpackung in-memory implementiert (`ZnsImportService`).
|
||||
* [x] **Legacy-Parser (CP850 Fixed-Width):**
|
||||
* `ZnsLegacyParsers` in `core:zns-parser` (KMP-Modul) implementiert.
|
||||
* Alle 4 Dateitypen (VEREIN01, LIZENZ01, PFERDE01, RICHT01) bytegenau gemappt. 4 Unit-Tests grün.
|
||||
* Alle 4 Dateitypen (VEREIN01, LIZENZ01, PFERDE01, RICHT01) bytegenau gemappt. RICHT01 verarbeitet Richter ('X') und Parcoursbauer ('Y'). ✅
|
||||
|
||||
### Phase 2: Domain-Mapping & Persistenz (👷 Backend Developer)
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
type: Reference
|
||||
status: ACTIVE
|
||||
owner: Lead Architect & ÖTO/FEI Rulebook Expert
|
||||
last_update: 2026-04-02
|
||||
last_update: 2026-04-05
|
||||
sources:
|
||||
- ÖTO 2026, Abschnitt A I, § 2 & § 3 & § 4
|
||||
- Domain Workshop 2026-03-17
|
||||
@@ -71,7 +71,7 @@ Die ÖTO definiert sparten- und klassenabhängige Schwellenwerte, ab wievielen S
|
||||
| Begriff | Definition | ÖTO-Referenz |
|
||||
|----------------|------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------|
|
||||
| **FEI-ID** | Eindeutige Identifikationsnummer der Internationalen Reiterlichen Vereinigung (FEI) für Reiter und Pferde. | FEI General Regulations |
|
||||
| **Funktionär** | Person mit einer definierten Rolle bei einem Turnier (Richter, Parcoursbauer, TBA, ...). Qualifikation wird gegen `RICHT01.DAT` geprüft. | ÖTO Funktionärs-Qualifikation |
|
||||
| **Funktionär** | Person mit einer definierten Rolle bei einem Turnier (Richter, Parcoursbauer, TBA, ...). Qualifikation wird gegen `RICHT01.DAT` geprüft. Im Code als Entität **`Funktionaer`** abgebildet. | ÖTO Funktionärs-Qualifikation |
|
||||
|
||||
### G
|
||||
|
||||
@@ -136,6 +136,7 @@ Die ÖTO definiert sparten- und klassenabhängige Schwellenwerte, ab wievielen S
|
||||
|
||||
| Begriff | Definition | ÖTO-Referenz |
|
||||
|------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------------------------|
|
||||
| **Reiter** | Eine Person, die an einem Bewerb teilnimmt. Spezialisierung einer Person mit pferdesportlichen Attributen (Lizenz, Startkarte). Im Code als Entität **`Reiter`** abgebildet. Datenquelle primär `LIZENZ01.DAT`. | ÖTO § 2 Abs. 11 |
|
||||
| **Satznummer** | *Pferd:* 10-stellige, rein numerische ID (`0000123456`). **Primärer Schlüssel für den Datenaustausch.** *Reiter:* 6-stellige, rein numerische ID. | ZNS-Schnittstelle |
|
||||
| **Serie** | Synonym für → *Cup*. Übergeordneter Wettbewerb, der Ergebnisse aus Bewerben bei **mindestens zwei Turnieren** aggregiert. Besitzt ein **eigenes Reglement** (siehe Abschnitt 4). | ÖTO § 2 Abs. 8 |
|
||||
| **Sparte** | Die unterschiedlichen Arten von Turnieren oder Bewerben (z.B. Dressur = CDN, Springen = CSN). Bestimmt das anzuwendende Richtverfahren und das Regelwerk. | ÖTO § 2 Abs. 9, § 3 Abs. 2 |
|
||||
@@ -162,7 +163,7 @@ Die ÖTO definiert sparten- und klassenabhängige Schwellenwerte, ab wievielen S
|
||||
| Begriff | Definition | ÖTO-Referenz |
|
||||
|-------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-----------------|
|
||||
| **Veranstaltung** | In unserer Software: Der Oberbegriff für jede Art von pferdesportlicher Veranstaltung, die von einem Verein durchgeführt wird. Erhält eine **intern vergebene ID**. Entspricht dem ÖTO-Oberbegriff „Pferdesportliche Veranstaltung" (§ 2 Abs. 1). Kann vom Typ Turnier, Reitertreffen, Sonderprüfung, PS&S oder Turnierartig sein. | ÖTO § 2 Abs. 1 |
|
||||
| **Veranstalter** | OEPS-Mitgliedsverein (über LFV angeschlossen), der eine Veranstaltung ausrichtet. Besitzt eine **Vereinsnummer**. | ÖTO § 2 Abs. 12 |
|
||||
| **Veranstalter** | OEPS-Mitgliedsverein (über LFV angeschlossen), der eine Veranstaltung ausrichtet. Besitzt eine **Vereinsnummer**. Im Code als Entität **`Verein`** abgebildet. | ÖTO § 2 Abs. 12 |
|
||||
| **Veranstaltungs‑Kassa** | Kassen- und Abrechnungsführer auf Ebene der → *Veranstaltung*. Konsolidiert alle Zahlungen, Belege und Rückgelder über mehrere → *Turniere* derselben Veranstaltung. Dient als zentrale Sammelkasse; kann Zahlvorgänge turnierübergreifend splitten und konsolidieren. | Billing Context |
|
||||
|
||||
### Z
|
||||
@@ -181,7 +182,7 @@ Die ÖTO definiert sparten- und klassenabhängige Schwellenwerte, ab wievielen S
|
||||
| Veranstaltung, Turnier, Ausschreibung, Veranstalter | `event-management-context` |
|
||||
| Bewerb, Abteilung, Startliste, Ergebnis, Richtverfahren | `competition-context` |
|
||||
| Nennung, Nennungs-Transfer, Startwunsch, ZNS-Import | `registration-context` |
|
||||
| Reiter, Pferd, Lizenz, Funktionär, Kopfnummer, Satznummer | `actor-context` |
|
||||
| Reiter, Pferd, Lizenz, Funktionär, Kopfnummer, Satznummer, Verein | `actor-context` |
|
||||
| Nenngeld, Startgeld, Konto, Transaktion, Sportförderbeitrag | `billing-context` |
|
||||
| Cup, Serie, Meisterschaft, Reglement, Endklassement | `series-context` *(Phase 2+)* |
|
||||
| Login, Rolle, Berechtigung | `identity-context` |
|
||||
@@ -234,4 +235,4 @@ Ein Reglement definiert typischerweise:
|
||||
---
|
||||
|
||||
*Erstellt: 2026-03-24 | Autoren: Lead Architect, ÖTO/FEI Rulebook Expert, Curator*
|
||||
*Basiert auf: ÖTO 2026 § 2, § 3, § 4 | Domain Workshop 2026-03-17 | Session 2026-03-24*
|
||||
*Basiert auf: ÖTO 2026 § 2, § 3, § 4 | Domain Workshop 2026-03-17 | Session 2026-03-24 | Update: 2026-04-05 (Verein-Renaming & Bereinigung)*
|
||||
|
||||
Reference in New Issue
Block a user