Integrate qualification master data (QualifikationMasterTable) with functionary models, update schema and repository logic, refactor satzID references, and harmonize database migration (V010).

This commit is contained in:
2026-04-06 13:59:14 +02:00
parent c35869f8ee
commit 9237882437
7 changed files with 64 additions and 21 deletions
@@ -5,14 +5,23 @@ import at.mocode.core.domain.model.DatenQuelleE
import at.mocode.core.utils.database.DatabaseFactory
import at.mocode.masterdata.domain.model.Funktionaer
import at.mocode.masterdata.domain.repository.FunktionaerRepository
import at.mocode.masterdata.infrastructure.persistence.funktionaer.*
import org.jetbrains.exposed.v1.core.*
import org.jetbrains.exposed.v1.jdbc.*
import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.inList
import org.jetbrains.exposed.v1.jdbc.deleteWhere
import org.jetbrains.exposed.v1.jdbc.insert
import org.jetbrains.exposed.v1.jdbc.selectAll
import org.jetbrains.exposed.v1.jdbc.update
import org.slf4j.LoggerFactory
import kotlin.uuid.Uuid
/**
* Exposed-basierte Implementierung des Funktionaer-Repositorys.
*
* Verwaltet die Persistenz von Funktionären und deren Qualifikationen.
* Die Qualifikationen werden beim Speichern gegen die [QualifikationMasterTable]
* aufgelöst, um Datenintegrität bezüglich offizieller ÖTO-Kürzel sicherzustellen.
*/
class FunktionaerExposedRepository : FunktionaerRepository {
private val log = LoggerFactory.getLogger(FunktionaerExposedRepository::class.java)
@@ -21,7 +30,7 @@ class FunktionaerExposedRepository : FunktionaerRepository {
return Funktionaer(
funktionaerId = row[FunktionaerTable.id],
personId = row[FunktionaerTable.personId],
satzId = row[FunktionaerTable.satzId] ?: "X",
satzId = row[FunktionaerTable.satzId],
satzNummer = row[FunktionaerTable.satzNummer] ?: 0,
name = row[FunktionaerTable.name],
qualifikationen = qualifikationen,
@@ -99,6 +108,8 @@ class FunktionaerExposedRepository : FunktionaerRepository {
}
// Qualifikationen synchronisieren (über Master-Daten Auflösung)
// Wir löschen bestehende Zuordnungen und bauen sie basierend auf den Master-Daten neu auf.
// Unbekannte Kürzel werden nicht persistiert, sondern geloggt.
FunktionaerQualifikationTable.deleteWhere { funktionaerId eq funktionaer.funktionaerId }
val typ = if (funktionaer.istRichter()) "RICHTER" else "PARCOURSBAUER"
@@ -10,15 +10,21 @@ import kotlin.uuid.ExperimentalUuidApi
/**
* Exposed-Tabellendefinition für die Funktionär-Entität.
* Speichert Basisdaten und Kontaktinformationen.
*/
object FunktionaerTable : Table("funktionaer") {
val id = uuid("funktionaer_id")
val personId = uuid("person_id").nullable()
// === ZNS.zip RICHT01.DAT === ANFANG ===
// === ZNS.zip RICHT01.DAT (Zentrales Nennungssystem) === ANFANG ===
/** Typ des Satzes: "X" = Richter, "Y" = Parcoursbauer */
val satzId = varchar("satz_id", 1)
/** 6-stellige Satznummer (eindeutig pro Typ) */
val satzNummer = integer("satz_nummer").nullable()
/** Vollständiger Name (Nachname, Vorname) */
val name = varchar("name", 200).nullable()
// === ZNS.zip RICHT01.DAT === ENDE ===
@@ -54,12 +60,19 @@ object FunktionaerTable : Table("funktionaer") {
/**
* Exposed-Tabellendefinition für die Qualifikation-Master-Daten.
* Enthält offizielle ÖTO/FEI Kürzel (z.B. "D", "S", "P1").
*/
object QualifikationMasterTable : Table("qualifikation_master") {
val id = uuid("qualifikation_id")
val code = varchar("code", 10) // z.B. "D", "S", "SPF", "P1"
val bezeichnung = varchar("bezeichnung", 100) // z.B. "Dressur", "Springpferde"
val typ = varchar("typ", 20) // "RICHTER" oder "PARCOURSBAUER"
/** Offizielles Kürzel (z.B. "SPF" für Springpferde) */
val code = varchar("code", 10)
/** Fachlich ausgeschriebene Bezeichnung */
val bezeichnung = varchar("bezeichnung", 100)
/** Bereich der Qualifikation: "RICHTER" oder "PARCOURSBAUER" */
val typ = varchar("typ", 20)
override val primaryKey = PrimaryKey(id)