Refactor master data infrastructure to streamline Reiter and Bundesland relationships, add V012 migration, harmonize domain models, implement repository methods for enhanced ZNS import logic, and update associated tests.

This commit is contained in:
2026-04-06 16:39:06 +02:00
parent 1a6f2ea7ad
commit 0ae9a1f1b8
15 changed files with 284 additions and 76 deletions
@@ -18,6 +18,7 @@ class BundeslandRepositoryImpl : BundeslandRepository {
return BundeslandDefinition(
bundeslandId = row[BundeslandTable.id],
landId = row[BundeslandTable.landId],
bundeslandNr = row[BundeslandTable.bundeslandNr],
oepsCode = row[BundeslandTable.oepsCode],
iso3166_2_Code = row[BundeslandTable.iso3166_2_Code],
name = row[BundeslandTable.name],
@@ -30,6 +31,12 @@ class BundeslandRepositoryImpl : BundeslandRepository {
)
}
override suspend fun findByNr(nr: Int): BundeslandDefinition? = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { BundeslandTable.bundeslandNr eq nr }
.map(::rowToBundeslandDefinition)
.singleOrNull()
}
override suspend fun findById(id: Uuid): BundeslandDefinition? = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { BundeslandTable.id eq id }
.map(::rowToBundeslandDefinition)
@@ -10,8 +10,9 @@ import org.jetbrains.exposed.v1.datetime.timestamp
* Exposed-Tabellendefinition für die Bundesland-Entität.
*/
object BundeslandTable : Table("bundesland") {
val id = uuid("bundesland_id")
val id = uuid("id")
val landId = uuid("land_id")
val bundeslandNr = integer("bundesland_nr").nullable()
val oepsCode = varchar("oeps_code", 10).nullable()
val iso3166_2_Code = varchar("iso_3166_2_code", 10).nullable()
val name = varchar("name", 100)
@@ -0,0 +1,45 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence.reiter
import at.mocode.masterdata.domain.model.Bundesland
import at.mocode.masterdata.domain.model.BundeslandDefinition
import at.mocode.masterdata.domain.repository.BundeslandRepository
import at.mocode.core.utils.database.DatabaseFactory
import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.jdbc.*
import kotlin.uuid.Uuid
/**
* Exposed-Implementierung des Bundesland-Repositorys.
* Hinweis: Implementiert nur die für den ZNS-Import notwendigen Methoden.
*/
class BundeslandExposedRepository : BundeslandRepository {
private fun rowToDom(row: ResultRow) = Bundesland(
id = row[BundeslandTable.id],
bundeslandNr = row[BundeslandTable.bundeslandNr],
bezeichnung = row[BundeslandTable.bezeichnung],
wappenUrl = row[BundeslandTable.wappenUrl]
)
override suspend fun findByNr(nr: Int): Bundesland? = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { BundeslandTable.bundeslandNr eq nr }
.map(::rowToDom)
.singleOrNull()
}
// Dummy-Implementierungen für das Interface, da derzeit nicht vom ZNS-Import benötigt
override suspend fun findById(id: Uuid): BundeslandDefinition? = null
override suspend fun findByOepsCode(oepsCode: String, landId: Uuid): BundeslandDefinition? = null
override suspend fun findByIso3166_2_Code(iso3166_2_Code: String): BundeslandDefinition? = null
override suspend fun findByCountry(landId: Uuid, activeOnly: Boolean, orderBySortierung: Boolean): List<BundeslandDefinition> = emptyList()
override suspend fun findByName(searchTerm: String, landId: Uuid?, limit: Int): List<BundeslandDefinition> = emptyList()
override suspend fun findAllActive(orderBySortierung: Boolean): List<BundeslandDefinition> = emptyList()
override suspend fun save(bundesland: BundeslandDefinition): BundeslandDefinition = bundesland
override suspend fun upsertByLandIdAndKuerzel(bundesland: BundeslandDefinition): BundeslandDefinition = bundesland
override suspend fun delete(id: Uuid): Boolean = false
override suspend fun existsByOepsCode(oepsCode: String, landId: Uuid): Boolean = false
override suspend fun existsByIso3166_2_Code(iso3166_2_Code: String): Boolean = false
override suspend fun countActiveByCountry(landId: Uuid): Long = 0L
}
@@ -30,6 +30,9 @@ class ReiterExposedRepository : ReiterRepository {
bundeslandNummer = row[ReiterTable.bundeslandNummer],
vereinsName = row[ReiterTable.vereinsName],
nation = row[ReiterTable.nation],
vereinId = row[ReiterTable.vereinId],
bundeslandId = row[ReiterTable.bundeslandId],
nationId = row[ReiterTable.nationId],
reiterLizenz = row[ReiterTable.reiterLizenz],
startkarte = row[ReiterTable.startkarte],
fahrLizenz = row[ReiterTable.fahrLizenz],
@@ -91,6 +94,9 @@ class ReiterExposedRepository : ReiterRepository {
it[bundeslandNummer] = reiter.bundeslandNummer
it[vereinsName] = reiter.vereinsName
it[nation] = reiter.nation
it[vereinId] = reiter.vereinId
it[bundeslandId] = reiter.bundeslandId
it[nationId] = reiter.nationId
it[reiterLizenz] = reiter.reiterLizenz
it[startkarte] = reiter.startkarte
it[fahrLizenz] = reiter.fahrLizenz
@@ -121,6 +127,9 @@ class ReiterExposedRepository : ReiterRepository {
it[bundeslandNummer] = reiter.bundeslandNummer
it[vereinsName] = reiter.vereinsName
it[nation] = reiter.nation
it[vereinId] = reiter.vereinId
it[bundeslandId] = reiter.bundeslandId
it[nationId] = reiter.nationId
it[reiterLizenz] = reiter.reiterLizenz
it[startkarte] = reiter.startkarte
it[fahrLizenz] = reiter.fahrLizenz
@@ -23,6 +23,11 @@ object ReiterTable : Table("reiter") {
val bundeslandNummer = integer("bundesland_nummer").nullable()
val vereinsName = varchar("vereins_name", 200).nullable()
val nation = varchar("nation", 10).nullable()
val vereinId = uuid("verein_id").nullable()
val bundeslandId = uuid("bundesland_id").nullable()
val nationId = uuid("nation_id").nullable()
val reiterLizenz = varchar("reiter_lizenz", 20).nullable()
val startkarte = varchar("startkarte", 20).nullable()
val fahrLizenz = varchar("fahr_lizenz", 20).nullable()
@@ -41,19 +46,6 @@ object ReiterTable : Table("reiter") {
// === 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()
@@ -68,5 +60,35 @@ object ReiterTable : Table("reiter") {
init {
index("idx_reiter_satznummer", isUnique = true, satznummer)
index("idx_reiter_name", isUnique = false, nachname, vorname)
index("idx_reiter_mitglied", isUnique = false, mitgliedsNummer)
}
}
/**
* Exposed-Tabellendefinition für die Bundesland-Mastertabelle.
*/
object BundeslandTable : Table("bundesland") {
val id = uuid("bundesland_id")
val bundeslandNr = integer("bundesland_nr").uniqueIndex()
val bezeichnung = varchar("bezeichnung", 100)
val wappenUrl = varchar("wappen_url", 255).nullable()
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
}
/**
* Exposed-Tabellendefinition für die Reiter-Lizenzen.
*/
object ReiterLizenzTable : Table("reiter_lizenz") {
val id = uuid("lizenz_id")
val reiterId = uuid("reiter_id")
val lizenzTyp = varchar("lizenz_typ", 50) // STARTKARTE, REITERLIZENZ, FAHRLIZENZ
val kuerzel = varchar("kuerzel", 20)
val gueltigBis = date("gueltig_bis").nullable()
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
}
@@ -66,6 +66,12 @@ class VereinExposedRepository : VereinRepository {
.singleOrNull()
}
override suspend fun findByExactName(vereinName: String): Verein? = DatabaseFactory.dbQuery {
VereinTable.selectAll().where { VereinTable.vereinName eq vereinName }
.map(::rowToVereinDomain)
.firstOrNull()
}
override suspend fun findByName(searchTerm: String, limit: Int): List<Verein> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
VereinTable.selectAll().where { VereinTable.vereinName like pattern }