chore: remove deprecated horses, clubs, officials, and persons services

- Deleted obsolete modules related to horses, clubs, officials, and persons services, including their configurations, build files, and database provisioning scripts.
- Cleaned up associated references in the project structure (e.g., `settings.gradle.kts`).
- Removed unused database tables and Spring beans related to these domains.

Signed-off-by: Stefan Mogeritsch <stefan.mo.co@gmail.com>
This commit is contained in:
2026-03-28 16:50:49 +01:00
parent 2cb3f0b125
commit c806660685
181 changed files with 4121 additions and 8694 deletions
@@ -1,240 +1,220 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import at.mocode.core.domain.model.SparteE
import at.mocode.core.utils.database.DatabaseFactory
import at.mocode.masterdata.domain.model.AltersklasseDefinition
import at.mocode.masterdata.domain.repository.AltersklasseRepository
import at.mocode.core.utils.database.DatabaseFactory
import org.jetbrains.exposed.v1.core.*
import org.jetbrains.exposed.v1.jdbc.*
import kotlin.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
/**
* Implementierung des AltersklasseRepository für die Datenbankzugriffe.
*
* Diese Implementierung verwendet Exposed SQL für den Datenbankzugriff
* und mappt zwischen der AltersklasseDefinition Domain-Entität und der AltersklasseTable.
*/
class AltersklasseRepositoryImpl : AltersklasseRepository {
/**
* Konvertiert eine Datenbankzeile in ein Domain-Objekt.
*/
private fun rowToAltersklasseDefinition(row: ResultRow): AltersklasseDefinition {
return AltersklasseDefinition(
altersklasseId = row[AltersklasseTable.id],
altersklasseCode = row[AltersklasseTable.altersklasseCode],
bezeichnung = row[AltersklasseTable.bezeichnung],
minAlter = row[AltersklasseTable.minAlter],
maxAlter = row[AltersklasseTable.maxAlter],
stichtagRegelText = row[AltersklasseTable.stichtagRegelText],
sparteFilter = row[AltersklasseTable.sparteFilter]?.let { SparteE.valueOf(it) },
geschlechtFilter = row[AltersklasseTable.geschlechtFilter],
oetoRegelReferenzId = row[AltersklasseTable.oetoRegelReferenzId],
istAktiv = row[AltersklasseTable.istAktiv],
createdAt = row[AltersklasseTable.createdAt].toInstant(TimeZone.UTC),
updatedAt = row[AltersklasseTable.updatedAt].toInstant(TimeZone.UTC)
)
private fun rowToAltersklasseDefinition(row: ResultRow): AltersklasseDefinition {
return AltersklasseDefinition(
altersklasseId = row[AltersklasseTable.id],
altersklasseCode = row[AltersklasseTable.altersklasseCode],
bezeichnung = row[AltersklasseTable.bezeichnung],
minAlter = row[AltersklasseTable.minAlter],
maxAlter = row[AltersklasseTable.maxAlter],
stichtagRegelText = row[AltersklasseTable.stichtagRegelText],
sparteFilter = row[AltersklasseTable.sparteFilter]?.let { SparteE.valueOf(it) },
geschlechtFilter = row[AltersklasseTable.geschlechtFilter],
oetoRegelReferenzId = row[AltersklasseTable.oetoRegelReferenzId],
istAktiv = row[AltersklasseTable.istAktiv],
createdAt = row[AltersklasseTable.createdAt],
updatedAt = row[AltersklasseTable.updatedAt]
)
}
override suspend fun findById(id: Uuid): AltersklasseDefinition? = DatabaseFactory.dbQuery {
AltersklasseTable.selectAll().where { AltersklasseTable.id eq id }
.map(::rowToAltersklasseDefinition)
.singleOrNull()
}
override suspend fun findByCode(altersklasseCode: String): AltersklasseDefinition? = DatabaseFactory.dbQuery {
AltersklasseTable.selectAll().where { AltersklasseTable.altersklasseCode eq altersklasseCode }
.map(::rowToAltersklasseDefinition)
.singleOrNull()
}
override suspend fun findByName(searchTerm: String, limit: Int): List<AltersklasseDefinition> =
DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
AltersklasseTable.selectAll().where { AltersklasseTable.bezeichnung like pattern }
.limit(limit)
.map(::rowToAltersklasseDefinition)
}
override suspend fun findById(id: Uuid): AltersklasseDefinition? = DatabaseFactory.dbQuery {
AltersklasseTable.selectAll().where { AltersklasseTable.id eq id }
.map(::rowToAltersklasseDefinition)
.singleOrNull()
}
override suspend fun findAllActive(sparteFilter: SparteE?, geschlechtFilter: Char?): List<AltersklasseDefinition> =
DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where { AltersklasseTable.istAktiv eq true }
override suspend fun findByCode(altersklasseCode: String): AltersklasseDefinition? = DatabaseFactory.dbQuery {
AltersklasseTable.selectAll().where { AltersklasseTable.altersklasseCode eq altersklasseCode }
.map(::rowToAltersklasseDefinition)
.singleOrNull()
}
override suspend fun findByName(searchTerm: String, limit: Int): List<AltersklasseDefinition> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
AltersklasseTable.selectAll().where { AltersklasseTable.bezeichnung like pattern }
.limit(limit)
.map(::rowToAltersklasseDefinition)
}
override suspend fun findAllActive(sparteFilter: SparteE?, geschlechtFilter: Char?): List<AltersklasseDefinition> = DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where { AltersklasseTable.istAktiv eq true }
sparteFilter?.let { sparte ->
query.andWhere {
(AltersklasseTable.sparteFilter eq sparte.name) or (AltersklasseTable.sparteFilter.isNull())
}
}
geschlechtFilter?.let { geschlecht ->
query.andWhere {
(AltersklasseTable.geschlechtFilter eq geschlecht) or (AltersklasseTable.geschlechtFilter.isNull())
}
}
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
}
override suspend fun findApplicableForAge(age: Int, sparteFilter: SparteE?, geschlechtFilter: Char?): List<AltersklasseDefinition> = DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where { AltersklasseTable.istAktiv eq true }
// Age range filter
sparteFilter?.let { sparte ->
query.andWhere {
(AltersklasseTable.minAlter.isNull() or (AltersklasseTable.minAlter lessEq age)) and
(AltersklasseTable.maxAlter.isNull() or (AltersklasseTable.maxAlter greaterEq age))
(AltersklasseTable.sparteFilter eq sparte.name) or (AltersklasseTable.sparteFilter.isNull())
}
}
sparteFilter?.let { sparte ->
query.andWhere {
(AltersklasseTable.sparteFilter eq sparte.name) or (AltersklasseTable.sparteFilter.isNull())
}
geschlechtFilter?.let { geschlecht ->
query.andWhere {
(AltersklasseTable.geschlechtFilter eq geschlecht) or (AltersklasseTable.geschlechtFilter.isNull())
}
}
geschlechtFilter?.let { geschlecht ->
query.andWhere {
(AltersklasseTable.geschlechtFilter eq geschlecht) or (AltersklasseTable.geschlechtFilter.isNull())
}
}
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
}
override suspend fun findBySparte(sparte: SparteE, activeOnly: Boolean): List<AltersklasseDefinition> = DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where {
(AltersklasseTable.sparteFilter eq sparte.name) or (AltersklasseTable.sparteFilter.isNull())
}
override suspend fun findApplicableForAge(
age: Int,
sparteFilter: SparteE?,
geschlechtFilter: Char?
): List<AltersklasseDefinition> = DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where { AltersklasseTable.istAktiv eq true }
if (activeOnly) {
query.andWhere { AltersklasseTable.istAktiv eq true }
}
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
query.andWhere {
(AltersklasseTable.minAlter.isNull() or (AltersklasseTable.minAlter lessEq age)) and
(AltersklasseTable.maxAlter.isNull() or (AltersklasseTable.maxAlter greaterEq age))
}
override suspend fun findByGeschlecht(geschlecht: Char, activeOnly: Boolean): List<AltersklasseDefinition> = DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where {
(AltersklasseTable.geschlechtFilter eq geschlecht) or (AltersklasseTable.geschlechtFilter.isNull())
}
if (activeOnly) {
query.andWhere { AltersklasseTable.istAktiv eq true }
}
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
sparteFilter?.let { sparte ->
query.andWhere {
(AltersklasseTable.sparteFilter eq sparte.name) or (AltersklasseTable.sparteFilter.isNull())
}
}
override suspend fun findByAgeRange(minAge: Int?, maxAge: Int?, activeOnly: Boolean): List<AltersklasseDefinition> = DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll()
minAge?.let { min ->
query.andWhere {
(AltersklasseTable.maxAlter.isNull()) or (AltersklasseTable.maxAlter greaterEq min)
}
}
maxAge?.let { max ->
query.andWhere {
(AltersklasseTable.minAlter.isNull()) or (AltersklasseTable.minAlter lessEq max)
}
}
if (activeOnly) {
query.andWhere { AltersklasseTable.istAktiv eq true }
}
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
geschlechtFilter?.let { geschlecht ->
query.andWhere {
(AltersklasseTable.geschlechtFilter eq geschlecht) or (AltersklasseTable.geschlechtFilter.isNull())
}
}
override suspend fun findByOetoRegelReferenz(oetoRegelReferenzId: Uuid): List<AltersklasseDefinition> = DatabaseFactory.dbQuery {
AltersklasseTable.selectAll().where { AltersklasseTable.oetoRegelReferenzId eq oetoRegelReferenzId }
.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
}
override suspend fun findBySparte(sparte: SparteE, activeOnly: Boolean): List<AltersklasseDefinition> =
DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where {
(AltersklasseTable.sparteFilter eq sparte.name) or (AltersklasseTable.sparteFilter.isNull())
}
if (activeOnly) {
query.andWhere { AltersklasseTable.istAktiv eq true }
}
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
}
override suspend fun save(altersklasse: AltersklasseDefinition): AltersklasseDefinition = DatabaseFactory.dbQuery {
val now = Clock.System.now()
val existingAltersklasse = AltersklasseTable.selectAll().where { AltersklasseTable.id eq altersklasse.altersklasseId }.singleOrNull()
override suspend fun findByGeschlecht(geschlecht: Char, activeOnly: Boolean): List<AltersklasseDefinition> =
DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where {
(AltersklasseTable.geschlechtFilter eq geschlecht) or (AltersklasseTable.geschlechtFilter.isNull())
}
if (existingAltersklasse == null) {
// Insert a new age class
AltersklasseTable.insert { stmt ->
stmt[id] = altersklasse.altersklasseId
stmt[altersklasseCode] = altersklasse.altersklasseCode
stmt[bezeichnung] = altersklasse.bezeichnung
stmt[minAlter] = altersklasse.minAlter
stmt[maxAlter] = altersklasse.maxAlter
stmt[stichtagRegelText] = altersklasse.stichtagRegelText
stmt[sparteFilter] = altersklasse.sparteFilter?.name
stmt[geschlechtFilter] = altersklasse.geschlechtFilter
stmt[oetoRegelReferenzId] = altersklasse.oetoRegelReferenzId
stmt[istAktiv] = altersklasse.istAktiv
stmt[createdAt] = altersklasse.createdAt.toLocalDateTime(TimeZone.UTC)
stmt[updatedAt] = now.toLocalDateTime(TimeZone.UTC)
}
} else {
// Update existing age class
AltersklasseTable.update({ AltersklasseTable.id eq altersklasse.altersklasseId }) { stmt ->
stmt[altersklasseCode] = altersklasse.altersklasseCode
stmt[bezeichnung] = altersklasse.bezeichnung
stmt[minAlter] = altersklasse.minAlter
stmt[maxAlter] = altersklasse.maxAlter
stmt[stichtagRegelText] = altersklasse.stichtagRegelText
stmt[sparteFilter] = altersklasse.sparteFilter?.name
stmt[geschlechtFilter] = altersklasse.geschlechtFilter
stmt[oetoRegelReferenzId] = altersklasse.oetoRegelReferenzId
stmt[istAktiv] = altersklasse.istAktiv
stmt[updatedAt] = now.toLocalDateTime(TimeZone.UTC)
}
}
if (activeOnly) {
query.andWhere { AltersklasseTable.istAktiv eq true }
}
altersklasse.copy(updatedAt = now)
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
}
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
AltersklasseTable.deleteWhere { AltersklasseTable.id eq id } > 0
override suspend fun findByAgeRange(minAge: Int?, maxAge: Int?, activeOnly: Boolean): List<AltersklasseDefinition> =
DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll()
if (minAge != null) {
query.andWhere { AltersklasseTable.minAlter greaterEq minAge }
}
if (maxAge != null) {
query.andWhere { AltersklasseTable.maxAlter lessEq maxAge }
}
if (activeOnly) {
query.andWhere { AltersklasseTable.istAktiv eq true }
}
query.orderBy(AltersklasseTable.bezeichnung to SortOrder.ASC)
.map(::rowToAltersklasseDefinition)
}
override suspend fun existsByCode(altersklasseCode: String): Boolean = DatabaseFactory.dbQuery {
AltersklasseTable.selectAll().where { AltersklasseTable.altersklasseCode eq altersklasseCode }
.count() > 0
override suspend fun findByOetoRegelReferenz(oetoRegelReferenzId: Uuid): List<AltersklasseDefinition> =
DatabaseFactory.dbQuery {
AltersklasseTable.selectAll().where { AltersklasseTable.oetoRegelReferenzId eq oetoRegelReferenzId }
.map(::rowToAltersklasseDefinition)
}
override suspend fun countActive(sparteFilter: SparteE?): Long = DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where { AltersklasseTable.istAktiv eq true }
override suspend fun save(altersklasse: AltersklasseDefinition): AltersklasseDefinition = DatabaseFactory.dbQuery {
val exists = AltersklasseTable.selectAll().where { AltersklasseTable.id eq altersklasse.altersklasseId }.any()
sparteFilter?.let { sparte ->
query.andWhere {
(AltersklasseTable.sparteFilter eq sparte.name) or (AltersklasseTable.sparteFilter.isNull())
}
}
query.count()
if (exists) {
AltersklasseTable.update({ AltersklasseTable.id eq altersklasse.altersklasseId }) {
it[altersklasseCode] = altersklasse.altersklasseCode
it[bezeichnung] = altersklasse.bezeichnung
it[minAlter] = altersklasse.minAlter
it[maxAlter] = altersklasse.maxAlter
it[stichtagRegelText] = altersklasse.stichtagRegelText
it[sparteFilter] = altersklasse.sparteFilter?.name
it[geschlechtFilter] = altersklasse.geschlechtFilter
it[oetoRegelReferenzId] = altersklasse.oetoRegelReferenzId
it[istAktiv] = altersklasse.istAktiv
it[updatedAt] = altersklasse.updatedAt
}
altersklasse
} else {
AltersklasseTable.insert {
it[id] = altersklasse.altersklasseId
it[altersklasseCode] = altersklasse.altersklasseCode
it[bezeichnung] = altersklasse.bezeichnung
it[minAlter] = altersklasse.minAlter
it[maxAlter] = altersklasse.maxAlter
it[stichtagRegelText] = altersklasse.stichtagRegelText
it[sparteFilter] = altersklasse.sparteFilter?.name
it[geschlechtFilter] = altersklasse.geschlechtFilter
it[oetoRegelReferenzId] = altersklasse.oetoRegelReferenzId
it[istAktiv] = altersklasse.istAktiv
it[createdAt] = altersklasse.createdAt
it[updatedAt] = altersklasse.updatedAt
}
altersklasse
}
}
override suspend fun isEligible(altersklasseId: Uuid, age: Int, geschlecht: Char): Boolean = DatabaseFactory.dbQuery {
val altersklasse = AltersklasseTable.selectAll().where {
(AltersklasseTable.id eq altersklasseId) and (AltersklasseTable.istAktiv eq true)
}.singleOrNull()
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
AltersklasseTable.deleteWhere { AltersklasseTable.id eq id } > 0
}
if (altersklasse == null) return@dbQuery false
override suspend fun existsByCode(altersklasseCode: String): Boolean = DatabaseFactory.dbQuery {
AltersklasseTable.selectAll().where { AltersklasseTable.altersklasseCode eq altersklasseCode }.any()
}
// Check age eligibility
val minAlter = altersklasse[AltersklasseTable.minAlter]
val maxAlter = altersklasse[AltersklasseTable.maxAlter]
val ageEligible = (minAlter == null || age >= minAlter) && (maxAlter == null || age <= maxAlter)
// Check gender eligibility
val geschlechtFilter = altersklasse[AltersklasseTable.geschlechtFilter]
val genderEligible = geschlechtFilter == null || geschlechtFilter == geschlecht
ageEligible && genderEligible
override suspend fun countActive(sparteFilter: SparteE?): Long = DatabaseFactory.dbQuery {
val query = AltersklasseTable.selectAll().where { AltersklasseTable.istAktiv eq true }
sparteFilter?.let { sparte ->
query.andWhere { (AltersklasseTable.sparteFilter eq sparte.name) or (AltersklasseTable.sparteFilter.isNull()) }
}
query.count()
}
override suspend fun isEligible(altersklasseId: Uuid, age: Int, geschlecht: Char): Boolean = DatabaseFactory.dbQuery {
AltersklasseTable.selectAll().where { AltersklasseTable.id eq altersklasseId }
.map {
val min = it[AltersklasseTable.minAlter]
val max = it[AltersklasseTable.maxAlter]
val g = it[AltersklasseTable.geschlechtFilter]
val ageOk = (min == null || age >= min) && (max == null || age <= max)
val geschlechtOk = (g == null || g == geschlecht)
ageOk && geschlechtOk
}.singleOrNull() ?: false
}
}
@@ -1,37 +1,38 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import org.jetbrains.exposed.v1.core.Table
import org.jetbrains.exposed.v1.core.kotlin.datetime.datetime
import org.jetbrains.exposed.v1.core.kotlin.datetime.CurrentDateTime
import org.jetbrains.exposed.v1.core.javaUUID
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
import org.jetbrains.exposed.v1.datetime.timestamp
/**
* Exposed-Tabellendefinition für die Altersklasse-Entität (Altersklassendefinitionen).
* Exposed-Tabellendefinition für die Altersklasse-Entität (Altersklassendefinition).
*
* Diese Tabelle speichert alle Informationen zu Altersklassen für Teilnehmer
* entsprechend der AltersklasseDefinition Domain-Entität.
*/
object AltersklasseTable : Table("altersklasse") {
val id = javaUUID("id").autoGenerate()
val altersklasseCode = varchar("altersklasse_code", 50).uniqueIndex()
val bezeichnung = varchar("bezeichnung", 200)
val minAlter = integer("min_alter").nullable()
val maxAlter = integer("max_alter").nullable()
val stichtagRegelText = varchar("stichtag_regel_text", 500).nullable()
val sparteFilter = varchar("sparte_filter", 50).nullable() // Enum as string
val geschlechtFilter = char("geschlecht_filter").nullable()
val oetoRegelReferenzId = javaUUID("oeto_regel_referenz_id").nullable()
val istAktiv = bool("ist_aktiv").default(true)
val createdAt = datetime("created_at").defaultExpression(CurrentDateTime)
val updatedAt = datetime("updated_at").defaultExpression(CurrentDateTime)
val id = uuid("id")
val altersklasseCode = varchar("altersklasse_code", 50).uniqueIndex()
val bezeichnung = varchar("bezeichnung", 200)
val minAlter = integer("min_alter").nullable()
val maxAlter = integer("max_alter").nullable()
val stichtagRegelText = varchar("stichtag_regel_text", 500).nullable()
val sparteFilter = varchar("sparte_filter", 50).nullable() // Enum as string
val geschlechtFilter = char("geschlecht_filter").nullable()
val oetoRegelReferenzId = uuid("oeto_regel_referenz_id").nullable()
val istAktiv = bool("ist_aktiv").default(true)
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
override val primaryKey = PrimaryKey(id)
init {
// Index for performance on common queries
index(customIndexName = "idx_altersklasse_aktiv", columns = arrayOf(istAktiv))
index(customIndexName = "idx_altersklasse_sparte", columns = arrayOf(sparteFilter))
index(customIndexName = "idx_altersklasse_geschlecht", columns = arrayOf(geschlechtFilter))
index(customIndexName = "idx_altersklasse_alter", columns = arrayOf(minAlter, maxAlter))
}
init {
// Index for performance on common queries
index(customIndexName = "idx_altersklasse_aktiv", columns = arrayOf(istAktiv))
index(customIndexName = "idx_altersklasse_sparte", columns = arrayOf(sparteFilter))
index(customIndexName = "idx_altersklasse_geschlecht", columns = arrayOf(geschlechtFilter))
index(customIndexName = "idx_altersklasse_alter", columns = arrayOf(minAlter, maxAlter))
}
}
@@ -1,158 +1,136 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import at.mocode.core.utils.database.DatabaseFactory
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.*
import org.jetbrains.exposed.v1.jdbc.*
import kotlin.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
/**
* Implementierung des BundeslandRepository für die Datenbankzugriffe.
*
* Diese Implementierung verwendet Exposed SQL für den Datenbankzugriff
* und mappt zwischen der BundeslandDefinition Domain-Entität und der BundeslandTable.
*/
class BundeslandRepositoryImpl : BundeslandRepository {
/**
* Konvertiert eine Datenbankzeile in ein Domain-Objekt.
*/
private fun rowToBundeslandDefinition(row: ResultRow): BundeslandDefinition {
return BundeslandDefinition(
bundeslandId = row[BundeslandTable.id],
landId = row[BundeslandTable.landId],
oepsCode = row[BundeslandTable.oepsCode],
iso3166_2_Code = row[BundeslandTable.iso3166_2_Code],
name = row[BundeslandTable.name],
kuerzel = row[BundeslandTable.kuerzel],
wappenUrl = row[BundeslandTable.wappenUrl],
istAktiv = row[BundeslandTable.istAktiv],
sortierReihenfolge = row[BundeslandTable.sortierReihenfolge],
createdAt = row[BundeslandTable.createdAt].toInstant(TimeZone.UTC),
updatedAt = row[BundeslandTable.updatedAt].toInstant(TimeZone.UTC)
)
private fun rowToBundeslandDefinition(row: ResultRow): BundeslandDefinition {
return BundeslandDefinition(
bundeslandId = row[BundeslandTable.id],
landId = row[BundeslandTable.landId],
oepsCode = row[BundeslandTable.oepsCode],
iso3166_2_Code = row[BundeslandTable.iso3166_2_Code],
name = row[BundeslandTable.name],
kuerzel = row[BundeslandTable.kuerzel],
wappenUrl = row[BundeslandTable.wappenUrl],
istAktiv = row[BundeslandTable.istAktiv],
sortierReihenfolge = row[BundeslandTable.sortierReihenfolge],
createdAt = row[BundeslandTable.createdAt],
updatedAt = row[BundeslandTable.updatedAt]
)
}
override suspend fun findById(id: Uuid): BundeslandDefinition? = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { BundeslandTable.id eq id }
.map(::rowToBundeslandDefinition)
.singleOrNull()
}
override suspend fun findByOepsCode(oepsCode: String, landId: Uuid): BundeslandDefinition? = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { (BundeslandTable.oepsCode eq oepsCode) and (BundeslandTable.landId eq landId) }
.map(::rowToBundeslandDefinition)
.singleOrNull()
}
override suspend fun findByIso3166_2_Code(iso3166_2_Code: String): BundeslandDefinition? = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { BundeslandTable.iso3166_2_Code eq iso3166_2_Code }
.map(::rowToBundeslandDefinition)
.singleOrNull()
}
override suspend fun findByCountry(
landId: Uuid,
activeOnly: Boolean,
orderBySortierung: Boolean
): List<BundeslandDefinition> = DatabaseFactory.dbQuery {
val query = BundeslandTable.selectAll().where { BundeslandTable.landId eq landId }
if (activeOnly) {
query.andWhere { BundeslandTable.istAktiv eq true }
}
if (orderBySortierung) {
query.orderBy(BundeslandTable.sortierReihenfolge to SortOrder.ASC, BundeslandTable.name to SortOrder.ASC)
} else {
query.orderBy(BundeslandTable.name to SortOrder.ASC)
}
query.map(::rowToBundeslandDefinition)
}
override suspend fun findByName(searchTerm: String, landId: Uuid?, limit: Int): List<BundeslandDefinition> =
DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
val query = BundeslandTable.selectAll().where { BundeslandTable.name like pattern }
landId?.let { query.andWhere { BundeslandTable.landId eq it } }
query.limit(limit).map(::rowToBundeslandDefinition)
}
override suspend fun findById(id: Uuid): BundeslandDefinition? = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { BundeslandTable.id eq id }
.map(::rowToBundeslandDefinition)
.singleOrNull()
override suspend fun findAllActive(orderBySortierung: Boolean): List<BundeslandDefinition> = DatabaseFactory.dbQuery {
val query = BundeslandTable.selectAll().where { BundeslandTable.istAktiv eq true }
if (orderBySortierung) {
query.orderBy(BundeslandTable.sortierReihenfolge to SortOrder.ASC, BundeslandTable.name to SortOrder.ASC)
} else {
query.orderBy(BundeslandTable.name to SortOrder.ASC)
}
query.map(::rowToBundeslandDefinition)
}
override suspend fun findByOepsCode(oepsCode: String, landId: Uuid): BundeslandDefinition? = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where {
(BundeslandTable.oepsCode eq oepsCode) and (BundeslandTable.landId eq landId)
}
.map(::rowToBundeslandDefinition)
.singleOrNull()
override suspend fun save(bundesland: BundeslandDefinition): BundeslandDefinition = DatabaseFactory.dbQuery {
val exists = BundeslandTable.selectAll().where { BundeslandTable.id eq bundesland.bundeslandId }.any()
if (exists) {
BundeslandTable.update({ BundeslandTable.id eq bundesland.bundeslandId }) {
it[landId] = bundesland.landId
it[oepsCode] = bundesland.oepsCode
it[iso3166_2_Code] = bundesland.iso3166_2_Code
it[name] = bundesland.name
it[kuerzel] = bundesland.kuerzel
it[wappenUrl] = bundesland.wappenUrl
it[istAktiv] = bundesland.istAktiv
it[sortierReihenfolge] = bundesland.sortierReihenfolge
it[updatedAt] = bundesland.updatedAt
}
bundesland
} else {
BundeslandTable.insert {
it[id] = bundesland.bundeslandId
it[landId] = bundesland.landId
it[oepsCode] = bundesland.oepsCode
it[iso3166_2_Code] = bundesland.iso3166_2_Code
it[name] = bundesland.name
it[kuerzel] = bundesland.kuerzel
it[wappenUrl] = bundesland.wappenUrl
it[istAktiv] = bundesland.istAktiv
it[sortierReihenfolge] = bundesland.sortierReihenfolge
it[createdAt] = bundesland.createdAt
it[updatedAt] = bundesland.updatedAt
}
bundesland
}
}
override suspend fun findByIso3166_2_Code(iso3166_2_Code: String): BundeslandDefinition? = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { BundeslandTable.iso3166_2_Code eq iso3166_2_Code }
.map(::rowToBundeslandDefinition)
.singleOrNull()
}
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
BundeslandTable.deleteWhere { BundeslandTable.id eq id } > 0
}
override suspend fun findByCountry(landId: Uuid, activeOnly: Boolean, orderBySortierung: Boolean): List<BundeslandDefinition> = DatabaseFactory.dbQuery {
val query = BundeslandTable.selectAll().where { BundeslandTable.landId eq landId }
override suspend fun existsByOepsCode(oepsCode: String, landId: Uuid): Boolean = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { (BundeslandTable.oepsCode eq oepsCode) and (BundeslandTable.landId eq landId) }
.any()
}
if (activeOnly) {
query.andWhere { BundeslandTable.istAktiv eq true }
}
override suspend fun existsByIso3166_2_Code(iso3166_2_Code: String): Boolean = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { BundeslandTable.iso3166_2_Code eq iso3166_2_Code }.any()
}
if (orderBySortierung) {
query.orderBy(BundeslandTable.sortierReihenfolge to SortOrder.ASC, BundeslandTable.name to SortOrder.ASC)
} else {
query.orderBy(BundeslandTable.name to SortOrder.ASC)
}
query.map(::rowToBundeslandDefinition)
}
override suspend fun findByName(searchTerm: String, landId: Uuid?, limit: Int): List<BundeslandDefinition> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
val query = BundeslandTable.selectAll().where { BundeslandTable.name like pattern }
landId?.let {
query.andWhere { BundeslandTable.landId eq it }
}
query.limit(limit).map(::rowToBundeslandDefinition)
}
override suspend fun findAllActive(orderBySortierung: Boolean): List<BundeslandDefinition> = DatabaseFactory.dbQuery {
val query = BundeslandTable.selectAll().where { BundeslandTable.istAktiv eq true }
if (orderBySortierung) {
query.orderBy(BundeslandTable.sortierReihenfolge to SortOrder.ASC, BundeslandTable.name to SortOrder.ASC)
} else {
query.orderBy(BundeslandTable.name to SortOrder.ASC)
}
query.map(::rowToBundeslandDefinition)
}
override suspend fun save(bundesland: BundeslandDefinition): BundeslandDefinition = DatabaseFactory.dbQuery {
val now = Clock.System.now()
val existingBundesland = BundeslandTable.selectAll().where { BundeslandTable.id eq bundesland.bundeslandId }.singleOrNull()
if (existingBundesland == null) {
// Insert a new federal state
BundeslandTable.insert { stmt ->
stmt[id] = bundesland.bundeslandId
stmt[landId] = bundesland.landId
stmt[oepsCode] = bundesland.oepsCode
stmt[iso3166_2_Code] = bundesland.iso3166_2_Code
stmt[name] = bundesland.name
stmt[kuerzel] = bundesland.kuerzel
stmt[wappenUrl] = bundesland.wappenUrl
stmt[istAktiv] = bundesland.istAktiv
stmt[sortierReihenfolge] = bundesland.sortierReihenfolge
stmt[createdAt] = bundesland.createdAt.toLocalDateTime(TimeZone.UTC)
stmt[updatedAt] = now.toLocalDateTime(TimeZone.UTC)
}
} else {
// Update existing federal state
BundeslandTable.update({ BundeslandTable.id eq bundesland.bundeslandId }) { stmt ->
stmt[landId] = bundesland.landId
stmt[oepsCode] = bundesland.oepsCode
stmt[iso3166_2_Code] = bundesland.iso3166_2_Code
stmt[name] = bundesland.name
stmt[kuerzel] = bundesland.kuerzel
stmt[wappenUrl] = bundesland.wappenUrl
stmt[istAktiv] = bundesland.istAktiv
stmt[sortierReihenfolge] = bundesland.sortierReihenfolge
stmt[updatedAt] = now.toLocalDateTime(TimeZone.UTC)
}
}
bundesland.copy(updatedAt = now)
}
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
BundeslandTable.deleteWhere { BundeslandTable.id eq id } > 0
}
override suspend fun existsByOepsCode(oepsCode: String, landId: Uuid): Boolean = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where {
(BundeslandTable.oepsCode eq oepsCode) and (BundeslandTable.landId eq landId)
}.count() > 0
}
override suspend fun existsByIso3166_2_Code(iso3166_2_Code: String): Boolean = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { BundeslandTable.iso3166_2_Code eq iso3166_2_Code }
.count() > 0
}
override suspend fun countActiveByCountry(landId: Uuid): Long = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where {
(BundeslandTable.landId eq landId) and (BundeslandTable.istAktiv eq true)
}.count()
}
override suspend fun countActiveByCountry(landId: Uuid): Long = DatabaseFactory.dbQuery {
BundeslandTable.selectAll().where { (BundeslandTable.landId eq landId) and (BundeslandTable.istAktiv eq true) }
.count()
}
}
@@ -1,35 +1,31 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import org.jetbrains.exposed.v1.core.Table
import org.jetbrains.exposed.v1.core.kotlin.datetime.datetime
import org.jetbrains.exposed.v1.core.kotlin.datetime.CurrentDateTime
import org.jetbrains.exposed.v1.core.javaUUID
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
import org.jetbrains.exposed.v1.datetime.timestamp
/**
* Exposed-Tabellendefinition für die Bundesland-Entität (Bundesländer/Regionen).
*
* Diese Tabelle speichert alle Informationen zu Bundesländern und subnationalen
* Verwaltungseinheiten entsprechend der BundeslandDefinition Domain-Entität.
* Exposed-Tabellendefinition für die Bundesland-Entität.
*/
object BundeslandTable : Table("bundesland") {
val id = javaUUID("id").autoGenerate()
val landId = javaUUID("land_id").references(LandTable.id)
val oepsCode = varchar("oeps_code", 10).nullable()
val iso3166_2_Code = varchar("iso_3166_2_code", 10).nullable()
val name = varchar("name", 100)
val kuerzel = varchar("kuerzel", 10).nullable()
val wappenUrl = varchar("wappen_url", 500).nullable()
val istAktiv = bool("ist_aktiv").default(true)
val sortierReihenfolge = integer("sortier_reihenfolge").nullable()
val createdAt = datetime("created_at").defaultExpression(CurrentDateTime)
val updatedAt = datetime("updated_at").defaultExpression(CurrentDateTime)
val id = uuid("bundesland_id")
val landId = uuid("land_id")
val oepsCode = varchar("oeps_code", 10).nullable()
val iso3166_2_Code = varchar("iso_3166_2_code", 10).nullable()
val name = varchar("name", 100)
val kuerzel = varchar("kuerzel", 10).nullable()
val wappenUrl = varchar("wappen_url", 255).nullable()
val istAktiv = bool("ist_aktiv").default(true)
val sortierReihenfolge = integer("sortier_reihenfolge").nullable()
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
override val primaryKey = PrimaryKey(id)
init {
// Unique constraint for OEPS code per country
uniqueIndex("uk_bundesland_oeps_land", oepsCode, landId)
// Unique constraint for ISO 3166-2 code globally
uniqueIndex("uk_bundesland_iso3166_2", iso3166_2_Code)
}
init {
uniqueIndex("idx_bundesland_oeps", oepsCode, landId)
uniqueIndex("idx_bundesland_iso", iso3166_2_Code)
}
}
@@ -0,0 +1,157 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import at.mocode.core.domain.model.DatenQuelleE
import at.mocode.core.domain.model.FunktionaerRolleE
import at.mocode.core.domain.model.RichterQualifikationE
import at.mocode.core.domain.model.SparteE
import at.mocode.core.utils.database.DatabaseFactory
import at.mocode.masterdata.domain.model.DomFunktionaer
import at.mocode.masterdata.domain.repository.FunktionaerRepository
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.Uuid
/**
* Exposed-basierte Implementierung des Funktionaer-Repositorys.
*/
class ExposedFunktionaerRepository : FunktionaerRepository {
private fun rowToDomFunktionaer(row: ResultRow): DomFunktionaer {
return DomFunktionaer(
funktionaerId = row[FunktionaerTable.id],
richterNummer = row[FunktionaerTable.richterNummer],
vorname = row[FunktionaerTable.vorname],
nachname = row[FunktionaerTable.nachname],
geburtsdatum = row[FunktionaerTable.geburtsdatum],
email = row[FunktionaerTable.email],
telefon = row[FunktionaerTable.telefon],
vereinsNummer = row[FunktionaerTable.vereinsNummer],
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 {
FunktionaerTable.selectAll().where { FunktionaerTable.id eq id }
.map(::rowToDomFunktionaer)
.singleOrNull()
}
override suspend fun findByRichterNummer(richterNummer: String): DomFunktionaer? = DatabaseFactory.dbQuery {
FunktionaerTable.selectAll().where { FunktionaerTable.richterNummer eq richterNummer }
.map(::rowToDomFunktionaer)
.singleOrNull()
}
override suspend fun findByName(searchTerm: String, limit: Int): List<DomFunktionaer> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
FunktionaerTable.selectAll()
.where { (FunktionaerTable.nachname like pattern) or (FunktionaerTable.vorname like pattern) }
.limit(limit)
.map(::rowToDomFunktionaer)
}
override suspend fun findByRolle(rolle: FunktionaerRolleE, activeOnly: Boolean): List<DomFunktionaer> =
DatabaseFactory.dbQuery {
// Rolle wird aktuell nicht in FunktionaerTable gespeichert.
// Falls benötigt, muss die Tabelle erweitert werden.
emptyList()
}
override suspend fun findByRichterQualifikation(
qualifikation: RichterQualifikationE,
activeOnly: Boolean
): List<DomFunktionaer> = DatabaseFactory.dbQuery {
// Qualifikationen werden aktuell nicht in FunktionaerTable gespeichert.
emptyList()
}
override suspend fun findBySparte(sparte: SparteE, activeOnly: Boolean): List<DomFunktionaer> =
DatabaseFactory.dbQuery {
emptyList()
}
override suspend fun findByVereinsNummer(vereinsNummer: String, activeOnly: Boolean): List<DomFunktionaer> =
DatabaseFactory.dbQuery {
val query = FunktionaerTable.selectAll().where { FunktionaerTable.vereinsNummer eq vereinsNummer }
if (activeOnly) {
query.andWhere { FunktionaerTable.istAktiv eq true }
}
query.map(::rowToDomFunktionaer)
}
override suspend fun findAllActive(limit: Int, offset: Int): List<DomFunktionaer> = DatabaseFactory.dbQuery {
FunktionaerTable.selectAll().where { FunktionaerTable.istAktiv eq true }
.limit(limit).offset(offset.toLong())
.map(::rowToDomFunktionaer)
}
override suspend fun findAll(limit: Int, offset: Int): List<DomFunktionaer> = DatabaseFactory.dbQuery {
FunktionaerTable.selectAll()
.limit(limit).offset(offset.toLong())
.map(::rowToDomFunktionaer)
}
override suspend fun save(funktionaer: DomFunktionaer): DomFunktionaer = DatabaseFactory.dbQuery {
val exists = FunktionaerTable.selectAll().where { FunktionaerTable.id eq funktionaer.funktionaerId }.any()
if (exists) {
FunktionaerTable.update({ FunktionaerTable.id eq funktionaer.funktionaerId }) {
it[richterNummer] = funktionaer.richterNummer
it[vorname] = funktionaer.vorname
it[nachname] = funktionaer.nachname
it[geburtsdatum] = funktionaer.geburtsdatum
it[email] = funktionaer.email
it[telefon] = funktionaer.telefon
it[vereinsNummer] = funktionaer.vereinsNummer
it[istAktiv] = funktionaer.istAktiv
it[bemerkungen] = funktionaer.bemerkungen
it[datenQuelle] = funktionaer.datenQuelle.name
it[updatedAt] = funktionaer.updatedAt
}
funktionaer
} else {
FunktionaerTable.insert {
it[id] = funktionaer.funktionaerId
it[richterNummer] = funktionaer.richterNummer
it[vorname] = funktionaer.vorname
it[nachname] = funktionaer.nachname
it[geburtsdatum] = funktionaer.geburtsdatum
it[email] = funktionaer.email
it[telefon] = funktionaer.telefon
it[vereinsNummer] = funktionaer.vereinsNummer
it[istAktiv] = funktionaer.istAktiv
it[bemerkungen] = funktionaer.bemerkungen
it[datenQuelle] = funktionaer.datenQuelle.name
it[createdAt] = funktionaer.createdAt
it[updatedAt] = funktionaer.updatedAt
}
funktionaer
}
}
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
FunktionaerTable.deleteWhere { FunktionaerTable.id eq id } > 0
}
override suspend fun countActive(): Long = DatabaseFactory.dbQuery {
FunktionaerTable.selectAll().where { FunktionaerTable.istAktiv eq true }.count()
}
override suspend fun countByRichterQualifikation(qualifikation: RichterQualifikationE, activeOnly: Boolean): Long =
DatabaseFactory.dbQuery {
// Aktuell keine Qualifikations-Speicherung
0L
}
override suspend fun existsByRichterNummer(richterNummer: String): Boolean = DatabaseFactory.dbQuery {
FunktionaerTable.selectAll().where { FunktionaerTable.richterNummer eq richterNummer }.any()
}
}
@@ -0,0 +1,177 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
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.utils.database.DatabaseFactory
import at.mocode.masterdata.domain.model.DomReiter
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.core.like
import org.jetbrains.exposed.v1.core.or
import org.jetbrains.exposed.v1.jdbc.*
import kotlin.uuid.Uuid
/**
* Exposed-basierte Implementierung des Reiter-Repositorys.
*/
class ExposedReiterRepository : ReiterRepository {
private fun rowToDomReiter(row: ResultRow): DomReiter {
return DomReiter(
reiterId = row[ReiterTable.id],
personId = row[ReiterTable.personId],
satznummer = row[ReiterTable.satznummer],
nachname = row[ReiterTable.nachname],
vorname = row[ReiterTable.vorname],
geburtsdatum = row[ReiterTable.geburtsdatum],
lizenzNummer = row[ReiterTable.lizenzNummer],
lizenzKlasse = LizenzKlasseE.valueOf(row[ReiterTable.lizenzKlasse]),
startkartAktiv = row[ReiterTable.startkartAktiv],
startkartSaison = row[ReiterTable.startkartSaison],
feiId = row[ReiterTable.feiId],
nation = row[ReiterTable.nation],
vereinsNummer = row[ReiterTable.vereinsNummer],
vereinsName = row[ReiterTable.vereinsName],
istGastreiter = row[ReiterTable.istGastreiter],
istAktiv = row[ReiterTable.istAktiv],
datenQuelle = DatenQuelleE.valueOf(row[ReiterTable.datenQuelle]),
createdAt = row[ReiterTable.createdAt],
updatedAt = row[ReiterTable.updatedAt]
)
}
override suspend fun findById(id: Uuid): DomReiter? = DatabaseFactory.dbQuery {
ReiterTable.selectAll().where { ReiterTable.id eq id }
.map(::rowToDomReiter)
.singleOrNull()
}
override suspend fun findBySatznummer(satznummer: String): DomReiter? = DatabaseFactory.dbQuery {
ReiterTable.selectAll().where { ReiterTable.satznummer eq satznummer }
.map(::rowToDomReiter)
.singleOrNull()
}
override suspend fun findByFeiId(feiId: String): DomReiter? = DatabaseFactory.dbQuery {
ReiterTable.selectAll().where { ReiterTable.feiId eq feiId }
.map(::rowToDomReiter)
.singleOrNull()
}
override suspend fun findByName(searchTerm: String, limit: Int): List<DomReiter> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
ReiterTable.selectAll().where { (ReiterTable.nachname like pattern) or (ReiterTable.vorname like pattern) }
.limit(limit)
.map(::rowToDomReiter)
}
override suspend fun findByVereinsNummer(vereinsNummer: String, activeOnly: Boolean): List<DomReiter> =
DatabaseFactory.dbQuery {
val query = ReiterTable.selectAll().where { ReiterTable.vereinsNummer eq vereinsNummer }
if (activeOnly) {
query.andWhere { ReiterTable.istAktiv eq true }
}
query.map(::rowToDomReiter)
}
override suspend fun findByLizenzKlasse(lizenzKlasse: LizenzKlasseE, activeOnly: Boolean): List<DomReiter> =
DatabaseFactory.dbQuery {
val query = ReiterTable.selectAll().where { ReiterTable.lizenzKlasse eq lizenzKlasse.name }
if (activeOnly) {
query.andWhere { ReiterTable.istAktiv eq true }
}
query.map(::rowToDomReiter)
}
override suspend fun findBySparte(sparte: SparteE, activeOnly: Boolean): List<DomReiter> = DatabaseFactory.dbQuery {
// Da wir in ReiterTable keinen sparteFilter haben, müssen wir ggf. über eine andere Tabelle gehen
// oder die Logik anpassen. Fürs erste geben wir eine leere Liste zurück oder suchen nach Name in Lizenz?
// TODO: Implementierung prüfen, falls Sparten-Lizenzierung in eigener Tabelle liegt.
emptyList()
}
override suspend fun findGastreiter(activeOnly: Boolean): List<DomReiter> = DatabaseFactory.dbQuery {
val query = ReiterTable.selectAll().where { ReiterTable.istGastreiter eq true }
if (activeOnly) {
query.andWhere { ReiterTable.istAktiv eq true }
}
query.map(::rowToDomReiter)
}
override suspend fun findAllActive(limit: Int, offset: Int): List<DomReiter> = DatabaseFactory.dbQuery {
ReiterTable.selectAll().where { ReiterTable.istAktiv eq true }
.limit(limit).offset(offset.toLong())
.map(::rowToDomReiter)
}
override suspend fun findAll(limit: Int, offset: Int): List<DomReiter> = DatabaseFactory.dbQuery {
ReiterTable.selectAll()
.limit(limit).offset(offset.toLong())
.map(::rowToDomReiter)
}
override suspend fun save(reiter: DomReiter): DomReiter = DatabaseFactory.dbQuery {
val exists = ReiterTable.selectAll().where { ReiterTable.id eq reiter.reiterId }.any()
if (exists) {
ReiterTable.update({ ReiterTable.id eq reiter.reiterId }) {
it[personId] = reiter.personId
it[satznummer] = reiter.satznummer
it[nachname] = reiter.nachname
it[vorname] = reiter.vorname
it[geburtsdatum] = reiter.geburtsdatum
it[lizenzNummer] = reiter.lizenzNummer
it[lizenzKlasse] = reiter.lizenzKlasse.name
it[startkartAktiv] = reiter.startkartAktiv
it[startkartSaison] = reiter.startkartSaison
it[feiId] = reiter.feiId
it[nation] = reiter.nation
it[vereinsNummer] = reiter.vereinsNummer
it[vereinsName] = reiter.vereinsName
it[istGastreiter] = reiter.istGastreiter
it[istAktiv] = reiter.istAktiv
it[datenQuelle] = reiter.datenQuelle.name
it[updatedAt] = reiter.updatedAt
}
reiter
} else {
ReiterTable.insert {
it[id] = reiter.reiterId
it[personId] = reiter.personId
it[satznummer] = reiter.satznummer
it[nachname] = reiter.nachname
it[vorname] = reiter.vorname
it[geburtsdatum] = reiter.geburtsdatum
it[lizenzNummer] = reiter.lizenzNummer
it[lizenzKlasse] = reiter.lizenzKlasse.name
it[startkartAktiv] = reiter.startkartAktiv
it[startkartSaison] = reiter.startkartSaison
it[feiId] = reiter.feiId
it[nation] = reiter.nation
it[vereinsNummer] = reiter.vereinsNummer
it[vereinsName] = reiter.vereinsName
it[istGastreiter] = reiter.istGastreiter
it[istAktiv] = reiter.istAktiv
it[datenQuelle] = reiter.datenQuelle.name
it[createdAt] = reiter.createdAt
it[updatedAt] = reiter.updatedAt
}
reiter
}
}
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
ReiterTable.deleteWhere { ReiterTable.id eq id } > 0
}
override suspend fun countActive(): Long = DatabaseFactory.dbQuery {
ReiterTable.selectAll().where { ReiterTable.istAktiv eq true }.count()
}
override suspend fun existsBySatznummer(satznummer: String): Boolean = DatabaseFactory.dbQuery {
ReiterTable.selectAll().where { ReiterTable.satznummer eq satznummer }.any()
}
}
@@ -0,0 +1,154 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
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.repository.VereinRepository
import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.or
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.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.like
import org.jetbrains.exposed.v1.jdbc.andWhere
import kotlin.uuid.Uuid
/**
* Exposed-basierte Implementierung des Verein-Repositorys.
*/
class ExposedVereinRepository : VereinRepository {
private fun rowToDomVerein(row: ResultRow): DomVerein {
return DomVerein(
vereinId = row[VereinTable.id],
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],
email = row[VereinTable.email],
telefon = row[VereinTable.telefon],
website = row[VereinTable.website],
oepsRegionNummer = row[VereinTable.oepsRegionNummer],
istVeranstalter = row[VereinTable.istVeranstalter],
istAktiv = row[VereinTable.istAktiv],
bemerkungen = row[VereinTable.bemerkungen],
datenQuelle = DatenQuelleE.valueOf(row[VereinTable.datenQuelle]),
createdAt = row[VereinTable.createdAt],
updatedAt = row[VereinTable.updatedAt]
)
}
override suspend fun findById(id: Uuid): DomVerein? = DatabaseFactory.dbQuery {
VereinTable.selectAll().where { VereinTable.id eq id }
.map(::rowToDomVerein)
.singleOrNull()
}
override suspend fun findByVereinsNummer(vereinsNummer: String): DomVerein? = DatabaseFactory.dbQuery {
VereinTable.selectAll().where { VereinTable.vereinsNummer eq vereinsNummer }
.map(::rowToDomVerein)
.singleOrNull()
}
override suspend fun findByName(searchTerm: String, limit: Int): List<DomVerein> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
VereinTable.selectAll().where { (VereinTable.name like pattern) or (VereinTable.kurzname like pattern) }
.limit(limit)
.map(::rowToDomVerein)
}
override suspend fun findByBundesland(bundesland: String, activeOnly: Boolean): List<DomVerein> =
DatabaseFactory.dbQuery {
val query = VereinTable.selectAll().where { VereinTable.bundesland eq bundesland }
if (activeOnly) {
query.andWhere { VereinTable.istAktiv eq true }
}
query.map(::rowToDomVerein)
}
override suspend fun findVeranstalter(activeOnly: Boolean): List<DomVerein> = DatabaseFactory.dbQuery {
val query = VereinTable.selectAll().where { VereinTable.istVeranstalter eq true }
if (activeOnly) {
query.andWhere { VereinTable.istAktiv eq true }
}
query.map(::rowToDomVerein)
}
override suspend fun findAllActive(limit: Int, offset: Int): List<DomVerein> = DatabaseFactory.dbQuery {
VereinTable.selectAll().where { VereinTable.istAktiv eq true }
.limit(limit).offset(offset.toLong())
.map(::rowToDomVerein)
}
override suspend fun findAll(limit: Int, offset: Int): List<DomVerein> = DatabaseFactory.dbQuery {
VereinTable.selectAll()
.limit(limit).offset(offset.toLong())
.map(::rowToDomVerein)
}
override suspend fun save(verein: DomVerein): DomVerein = 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[bundesland] = verein.bundesland
it[ort] = verein.ort
it[plz] = verein.plz
it[strasse] = verein.strasse
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[bemerkungen] = verein.bemerkungen
it[datenQuelle] = verein.datenQuelle.name
it[updatedAt] = verein.updatedAt
}
verein
} else {
VereinTable.insert {
it[id] = verein.vereinId
it[vereinsNummer] = verein.vereinsNummer
it[name] = verein.name
it[kurzname] = verein.kurzname
it[bundesland] = verein.bundesland
it[ort] = verein.ort
it[plz] = verein.plz
it[strasse] = verein.strasse
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[bemerkungen] = verein.bemerkungen
it[datenQuelle] = verein.datenQuelle.name
it[createdAt] = verein.createdAt
it[updatedAt] = verein.updatedAt
}
verein
}
}
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
VereinTable.deleteWhere { VereinTable.id eq id } > 0
}
override suspend fun countActive(): Long = DatabaseFactory.dbQuery {
VereinTable.selectAll().where { VereinTable.istAktiv eq true }.count()
}
override suspend fun existsByVereinsNummer(vereinsNummer: String): Boolean = DatabaseFactory.dbQuery {
VereinTable.selectAll().where { VereinTable.vereinsNummer eq vereinsNummer }.any()
}
}
@@ -0,0 +1,30 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import org.jetbrains.exposed.v1.core.Table
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
import org.jetbrains.exposed.v1.datetime.date
import org.jetbrains.exposed.v1.datetime.timestamp
/**
* Exposed-Tabellendefinition für die Funktionär-Entität.
*/
object FunktionaerTable : Table("funktionaer") {
val id = uuid("funktionaer_id")
val richterNummer = varchar("richter_nummer", 10).nullable().uniqueIndex()
val vorname = varchar("vorname", 100)
val nachname = varchar("nachname", 100)
val geburtsdatum = date("geburtsdatum").nullable()
val email = varchar("email", 200).nullable()
val telefon = varchar("telefon", 50).nullable()
val vereinsNummer = varchar("vereins_nummer", 10).nullable()
val istAktiv = bool("ist_aktiv").default(true)
val bemerkungen = text("bemerkungen").nullable()
val datenQuelle = varchar("daten_quelle", 50)
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
}
@@ -0,0 +1,286 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
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.repository.HorseRepository
import org.jetbrains.exposed.v1.core.*
import org.jetbrains.exposed.v1.jdbc.*
import kotlin.uuid.Uuid
/**
* Exposed-basierte Implementierung des Horse-Repositorys.
*/
class HorseRepositoryImpl : HorseRepository {
private fun rowToDomPferd(row: ResultRow): DomPferd {
return DomPferd(
pferdId = row[HorseTable.id],
pferdeName = row[HorseTable.pferdeName],
geschlecht = PferdeGeschlechtE.valueOf(row[HorseTable.geschlecht]),
geburtsdatum = row[HorseTable.geburtsdatum],
rasse = row[HorseTable.rasse],
farbe = row[HorseTable.farbe],
besitzerId = row[HorseTable.besitzerId],
verantwortlichePersonId = row[HorseTable.verantwortlichePersonId],
zuechterName = row[HorseTable.zuechterName],
zuchtbuchNummer = row[HorseTable.zuchtbuchNummer],
lebensnummer = row[HorseTable.lebensnummer],
chipNummer = row[HorseTable.chipNummer],
passNummer = row[HorseTable.passNummer],
oepsNummer = row[HorseTable.oepsNummer],
feiNummer = row[HorseTable.feiNummer],
vaterName = row[HorseTable.vaterName],
mutterName = row[HorseTable.mutterName],
mutterVaterName = row[HorseTable.mutterVaterName],
stockmass = row[HorseTable.stockmass],
istAktiv = row[HorseTable.istAktiv],
bemerkungen = row[HorseTable.bemerkungen],
datenQuelle = DatenQuelleE.valueOf(row[HorseTable.datenQuelle]),
createdAt = row[HorseTable.createdAt],
updatedAt = row[HorseTable.updatedAt]
)
}
override suspend fun findById(id: Uuid): DomPferd? = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.id eq id }
.map(::rowToDomPferd)
.singleOrNull()
}
override suspend fun findByLebensnummer(lebensnummer: String): DomPferd? = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.lebensnummer eq lebensnummer }
.map(::rowToDomPferd)
.singleOrNull()
}
override suspend fun findByChipNummer(chipNummer: String): DomPferd? = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.chipNummer eq chipNummer }
.map(::rowToDomPferd)
.singleOrNull()
}
override suspend fun findByPassNummer(passNummer: String): DomPferd? = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.passNummer eq passNummer }
.map(::rowToDomPferd)
.singleOrNull()
}
override suspend fun findByOepsNummer(oepsNummer: String): DomPferd? = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.oepsNummer eq oepsNummer }
.map(::rowToDomPferd)
.singleOrNull()
}
override suspend fun findByFeiNummer(feiNummer: String): DomPferd? = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.feiNummer eq feiNummer }
.map(::rowToDomPferd)
.singleOrNull()
}
override suspend fun findByName(searchTerm: String, limit: Int): List<DomPferd> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
HorseTable.selectAll().where { HorseTable.pferdeName like pattern }
.limit(limit)
.map(::rowToDomPferd)
}
override suspend fun findByOwnerId(ownerId: Uuid, activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
val query = HorseTable.selectAll().where { HorseTable.besitzerId eq ownerId }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.map(::rowToDomPferd)
}
override suspend fun findByResponsiblePersonId(responsiblePersonId: Uuid, activeOnly: Boolean): List<DomPferd> =
DatabaseFactory.dbQuery {
val query = HorseTable.selectAll().where { HorseTable.verantwortlichePersonId eq responsiblePersonId }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.map(::rowToDomPferd)
}
override suspend fun findByGeschlecht(
geschlecht: PferdeGeschlechtE,
activeOnly: Boolean,
limit: Int
): List<DomPferd> = DatabaseFactory.dbQuery {
val query = HorseTable.selectAll().where { HorseTable.geschlecht eq geschlecht.name }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.limit(limit).map(::rowToDomPferd)
}
override suspend fun findByRasse(rasse: String, activeOnly: Boolean, limit: Int): List<DomPferd> =
DatabaseFactory.dbQuery {
val query = HorseTable.selectAll().where { HorseTable.rasse eq rasse }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.limit(limit).map(::rowToDomPferd)
}
override suspend fun findByBirthYear(birthYear: Int, activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
// In Exposed v1 gibt es kein directes year() für date Spalten ohne extra Extension.
// Wir suchen im Datumsbereich.
val startDate = kotlinx.datetime.LocalDate(birthYear, 1, 1)
val endDate = kotlinx.datetime.LocalDate(birthYear, 12, 31)
val query = HorseTable.selectAll()
.where { (HorseTable.geburtsdatum greaterEq startDate) and (HorseTable.geburtsdatum lessEq endDate) }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.map(::rowToDomPferd)
}
override suspend fun findByBirthYearRange(fromYear: Int, toYear: Int, activeOnly: Boolean): List<DomPferd> =
DatabaseFactory.dbQuery {
val startDate = kotlinx.datetime.LocalDate(fromYear, 1, 1)
val endDate = kotlinx.datetime.LocalDate(toYear, 12, 31)
val query = HorseTable.selectAll()
.where { (HorseTable.geburtsdatum greaterEq startDate) and (HorseTable.geburtsdatum lessEq endDate) }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.map(::rowToDomPferd)
}
override suspend fun findAllActive(limit: Int): List<DomPferd> = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.istAktiv eq true }
.limit(limit)
.map(::rowToDomPferd)
}
override suspend fun findOepsRegistered(activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
val query = HorseTable.selectAll().where { HorseTable.oepsNummer.isNotNull() }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.map(::rowToDomPferd)
}
override suspend fun findFeiRegistered(activeOnly: Boolean): List<DomPferd> = DatabaseFactory.dbQuery {
val query = HorseTable.selectAll().where { HorseTable.feiNummer.isNotNull() }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.map(::rowToDomPferd)
}
override suspend fun save(horse: DomPferd): DomPferd = DatabaseFactory.dbQuery {
val exists = HorseTable.selectAll().where { HorseTable.id eq horse.pferdId }.any()
if (exists) {
HorseTable.update({ HorseTable.id eq horse.pferdId }) {
it[pferdeName] = horse.pferdeName
it[geschlecht] = horse.geschlecht.name
it[geburtsdatum] = horse.geburtsdatum
it[rasse] = horse.rasse
it[farbe] = horse.farbe
it[besitzerId] = horse.besitzerId
it[verantwortlichePersonId] = horse.verantwortlichePersonId
it[zuechterName] = horse.zuechterName
it[zuchtbuchNummer] = horse.zuchtbuchNummer
it[lebensnummer] = horse.lebensnummer
it[chipNummer] = horse.chipNummer
it[passNummer] = horse.passNummer
it[oepsNummer] = horse.oepsNummer
it[feiNummer] = horse.feiNummer
it[vaterName] = horse.vaterName
it[mutterName] = horse.mutterName
it[mutterVaterName] = horse.mutterVaterName
it[stockmass] = horse.stockmass
it[istAktiv] = horse.istAktiv
it[bemerkungen] = horse.bemerkungen
it[datenQuelle] = horse.datenQuelle.name
it[updatedAt] = horse.updatedAt
}
horse
} else {
HorseTable.insert {
it[id] = horse.pferdId
it[pferdeName] = horse.pferdeName
it[geschlecht] = horse.geschlecht.name
it[geburtsdatum] = horse.geburtsdatum
it[rasse] = horse.rasse
it[farbe] = horse.farbe
it[besitzerId] = horse.besitzerId
it[verantwortlichePersonId] = horse.verantwortlichePersonId
it[zuechterName] = horse.zuechterName
it[zuchtbuchNummer] = horse.zuchtbuchNummer
it[lebensnummer] = horse.lebensnummer
it[chipNummer] = horse.chipNummer
it[passNummer] = horse.passNummer
it[oepsNummer] = horse.oepsNummer
it[feiNummer] = horse.feiNummer
it[vaterName] = horse.vaterName
it[mutterName] = horse.mutterName
it[mutterVaterName] = horse.mutterVaterName
it[stockmass] = horse.stockmass
it[istAktiv] = horse.istAktiv
it[bemerkungen] = horse.bemerkungen
it[datenQuelle] = horse.datenQuelle.name
it[createdAt] = horse.createdAt
it[updatedAt] = horse.updatedAt
}
horse
}
}
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
HorseTable.deleteWhere { HorseTable.id eq id } > 0
}
override suspend fun existsByLebensnummer(lebensnummer: String): Boolean = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.lebensnummer eq lebensnummer }.any()
}
override suspend fun existsByChipNummer(chipNummer: String): Boolean = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.chipNummer eq chipNummer }.any()
}
override suspend fun existsByPassNummer(passNummer: String): Boolean = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.passNummer eq passNummer }.any()
}
override suspend fun existsByOepsNummer(oepsNummer: String): Boolean = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.oepsNummer eq oepsNummer }.any()
}
override suspend fun existsByFeiNummer(feiNummer: String): Boolean = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.feiNummer eq feiNummer }.any()
}
override suspend fun countActive(): Long = DatabaseFactory.dbQuery {
HorseTable.selectAll().where { HorseTable.istAktiv eq true }.count()
}
override suspend fun countByOwnerId(ownerId: Uuid, activeOnly: Boolean): Long = DatabaseFactory.dbQuery {
val query = HorseTable.selectAll().where { HorseTable.besitzerId eq ownerId }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.count()
}
override suspend fun countOepsRegistered(activeOnly: Boolean): Long = DatabaseFactory.dbQuery {
val query = HorseTable.selectAll().where { HorseTable.oepsNummer.isNotNull() }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.count()
}
override suspend fun countFeiRegistered(activeOnly: Boolean): Long = DatabaseFactory.dbQuery {
val query = HorseTable.selectAll().where { HorseTable.feiNummer.isNotNull() }
if (activeOnly) {
query.andWhere { HorseTable.istAktiv eq true }
}
query.count()
}
}
@@ -0,0 +1,45 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import org.jetbrains.exposed.v1.core.Table
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
import org.jetbrains.exposed.v1.datetime.date
import org.jetbrains.exposed.v1.datetime.timestamp
/**
* Exposed-Tabellendefinition für die Pferd-Entität.
*/
object HorseTable : Table("horse") {
val id = uuid("horse_id")
val pferdeName = varchar("pferde_name", 200)
val geschlecht = varchar("geschlecht", 20)
val geburtsdatum = date("geburtsdatum").nullable()
val rasse = varchar("rasse", 100).nullable()
val farbe = varchar("farbe", 100).nullable()
val besitzerId = uuid("besitzer_id").nullable()
val verantwortlichePersonId = uuid("verantwortliche_person_id").nullable()
val zuechterName = varchar("zuechter_name", 200).nullable()
val zuchtbuchNummer = varchar("zuchtbuch_nummer", 50).nullable()
val lebensnummer = varchar("lebensnummer", 50).nullable()
val chipNummer = varchar("chip_nummer", 50).nullable()
val passNummer = varchar("pass_nummer", 50).nullable()
val oepsNummer = varchar("oeps_nummer", 50).nullable()
val feiNummer = varchar("fei_nummer", 50).nullable()
val vaterName = varchar("vater_name", 200).nullable()
val mutterName = varchar("mutter_name", 200).nullable()
val mutterVaterName = varchar("mutter_vater_name", 200).nullable()
val stockmass = integer("stockmass").nullable()
val istAktiv = bool("ist_aktiv").default(true)
val bemerkungen = text("bemerkungen").nullable()
val datenQuelle = varchar("daten_quelle", 50)
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
init {
index("idx_horse_lebensnummer", isUnique = false, lebensnummer)
index("idx_horse_name", isUnique = false, pferdeName)
}
}
@@ -1,28 +1,25 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import at.mocode.core.utils.database.DatabaseFactory
import at.mocode.masterdata.domain.model.LandDefinition
import at.mocode.masterdata.domain.repository.LandRepository
import at.mocode.core.utils.database.DatabaseFactory
import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.or
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.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.like
import kotlin.uuid.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
/**
* Implementierung des LandRepository für die Datenbankzugriffe.
*
* Diese Implementierung verwendet Exposed SQL für den Datenbankzugriff
* und mappt zwischen der LandDefinition Domain-Entität und der LandTable.
*/
class LandRepositoryImpl : LandRepository {
/**
* Konvertiert eine Datenbankzeile in ein Domain-Objekt.
*/
private fun rowToLandDefinition(row: ResultRow): LandDefinition {
return LandDefinition(
landId = row[LandTable.id],
@@ -36,8 +33,8 @@ class LandRepositoryImpl : LandRepository {
istEwrMitglied = row[LandTable.istEwrMitglied],
istAktiv = row[LandTable.istAktiv],
sortierReihenfolge = row[LandTable.sortierReihenfolge],
createdAt = row[LandTable.createdAt].toInstant(TimeZone.UTC),
updatedAt = row[LandTable.updatedAt].toInstant(TimeZone.UTC)
createdAt = row[LandTable.createdAt],
updatedAt = row[LandTable.updatedAt]
)
}
@@ -48,90 +45,82 @@ class LandRepositoryImpl : LandRepository {
}
override suspend fun findByIsoAlpha2Code(isoAlpha2Code: String): LandDefinition? = DatabaseFactory.dbQuery {
LandTable.selectAll().where { LandTable.isoAlpha2Code eq isoAlpha2Code }
LandTable.selectAll().where { LandTable.isoAlpha2Code eq isoAlpha2Code.uppercase() }
.map(::rowToLandDefinition)
.singleOrNull()
}
override suspend fun findByIsoAlpha3Code(isoAlpha3Code: String): LandDefinition? = DatabaseFactory.dbQuery {
LandTable.selectAll().where { LandTable.isoAlpha3Code eq isoAlpha3Code }
LandTable.selectAll().where { LandTable.isoAlpha3Code eq isoAlpha3Code.uppercase() }
.map(::rowToLandDefinition)
.singleOrNull()
}
override suspend fun findByName(searchTerm: String, limit: Int): List<LandDefinition> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
LandTable.selectAll().where {
(LandTable.nameDeutsch like pattern) or
(LandTable.nameEnglisch like pattern)
}
.limit(limit)
.map(::rowToLandDefinition)
}
override suspend fun findAllActive(orderBySortierung: Boolean): List<LandDefinition> = DatabaseFactory.dbQuery {
val query = LandTable.selectAll().where { LandTable.istAktiv eq true }
if (orderBySortierung) {
query.orderBy(LandTable.sortierReihenfolge to SortOrder.ASC, LandTable.nameDeutsch to SortOrder.ASC)
} else {
query.orderBy(LandTable.nameDeutsch to SortOrder.ASC)
}
query.map(::rowToLandDefinition)
}
override suspend fun findByName(searchTerm: String, limit: Int): List<LandDefinition> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
LandTable.selectAll()
.where { (LandTable.nameDeutsch like pattern) or (LandTable.nameEnglisch like pattern) }
.limit(limit)
.map(::rowToLandDefinition)
}
override suspend fun findEuMembers(): List<LandDefinition> = DatabaseFactory.dbQuery {
LandTable.selectAll().where { (LandTable.istEuMitglied eq true) and (LandTable.istAktiv eq true) }
.orderBy(LandTable.sortierReihenfolge to SortOrder.ASC, LandTable.nameDeutsch to SortOrder.ASC)
LandTable.selectAll().where { LandTable.istEuMitglied eq true }
.orderBy(LandTable.nameDeutsch to SortOrder.ASC)
.map(::rowToLandDefinition)
}
override suspend fun findEwrMembers(): List<LandDefinition> = DatabaseFactory.dbQuery {
LandTable.selectAll().where { (LandTable.istEwrMitglied eq true) and (LandTable.istAktiv eq true) }
.orderBy(LandTable.sortierReihenfolge to SortOrder.ASC, LandTable.nameDeutsch to SortOrder.ASC)
LandTable.selectAll().where { LandTable.istEwrMitglied eq true }
.orderBy(LandTable.nameDeutsch to SortOrder.ASC)
.map(::rowToLandDefinition)
}
override suspend fun save(land: LandDefinition): LandDefinition = DatabaseFactory.dbQuery {
val now = Clock.System.now()
val existingLand = LandTable.selectAll().where { LandTable.id eq land.landId }.singleOrNull()
if (existingLand == null) {
// Insert a new country
LandTable.insert { stmt ->
stmt[id] = land.landId
stmt[isoAlpha2Code] = land.isoAlpha2Code
stmt[isoAlpha3Code] = land.isoAlpha3Code
stmt[isoNumerischerCode] = land.isoNumerischerCode
stmt[nameDeutsch] = land.nameDeutsch
stmt[nameEnglisch] = land.nameEnglisch
stmt[wappenUrl] = land.wappenUrl
stmt[istEuMitglied] = land.istEuMitglied
stmt[istEwrMitglied] = land.istEwrMitglied
stmt[istAktiv] = land.istAktiv
stmt[sortierReihenfolge] = land.sortierReihenfolge
stmt[createdAt] = land.createdAt.toLocalDateTime(TimeZone.UTC)
stmt[updatedAt] = now.toLocalDateTime(TimeZone.UTC)
val exists = LandTable.selectAll().where { LandTable.id eq land.landId }.any()
if (exists) {
LandTable.update({ LandTable.id eq land.landId }) {
it[isoAlpha2Code] = land.isoAlpha2Code.uppercase()
it[isoAlpha3Code] = land.isoAlpha3Code.uppercase()
it[isoNumerischerCode] = land.isoNumerischerCode
it[nameDeutsch] = land.nameDeutsch
it[nameEnglisch] = land.nameEnglisch
it[wappenUrl] = land.wappenUrl
it[istEuMitglied] = land.istEuMitglied
it[istEwrMitglied] = land.istEwrMitglied
it[istAktiv] = land.istAktiv
it[sortierReihenfolge] = land.sortierReihenfolge
it[updatedAt] = land.updatedAt
}
land
} else {
// Update existing country
LandTable.update({ LandTable.id eq land.landId }) { stmt ->
stmt[isoAlpha2Code] = land.isoAlpha2Code
stmt[isoAlpha3Code] = land.isoAlpha3Code
stmt[isoNumerischerCode] = land.isoNumerischerCode
stmt[nameDeutsch] = land.nameDeutsch
stmt[nameEnglisch] = land.nameEnglisch
stmt[wappenUrl] = land.wappenUrl
stmt[istEuMitglied] = land.istEuMitglied
stmt[istEwrMitglied] = land.istEwrMitglied
stmt[istAktiv] = land.istAktiv
stmt[sortierReihenfolge] = land.sortierReihenfolge
stmt[updatedAt] = now.toLocalDateTime(TimeZone.UTC)
LandTable.insert {
it[id] = land.landId
it[isoAlpha2Code] = land.isoAlpha2Code.uppercase()
it[isoAlpha3Code] = land.isoAlpha3Code.uppercase()
it[isoNumerischerCode] = land.isoNumerischerCode
it[nameDeutsch] = land.nameDeutsch
it[nameEnglisch] = land.nameEnglisch
it[wappenUrl] = land.wappenUrl
it[istEuMitglied] = land.istEuMitglied
it[istEwrMitglied] = land.istEwrMitglied
it[istAktiv] = land.istAktiv
it[sortierReihenfolge] = land.sortierReihenfolge
it[createdAt] = land.createdAt
it[updatedAt] = land.updatedAt
}
land
}
land.copy(updatedAt = now)
}
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
@@ -139,13 +128,11 @@ class LandRepositoryImpl : LandRepository {
}
override suspend fun existsByIsoAlpha2Code(isoAlpha2Code: String): Boolean = DatabaseFactory.dbQuery {
LandTable.selectAll().where { LandTable.isoAlpha2Code eq isoAlpha2Code }
.count() > 0
LandTable.selectAll().where { LandTable.isoAlpha2Code eq isoAlpha2Code.uppercase() }.any()
}
override suspend fun existsByIsoAlpha3Code(isoAlpha3Code: String): Boolean = DatabaseFactory.dbQuery {
LandTable.selectAll().where { LandTable.isoAlpha3Code eq isoAlpha3Code }
.count() > 0
LandTable.selectAll().where { LandTable.isoAlpha3Code eq isoAlpha3Code.uppercase() }.any()
}
override suspend fun countActive(): Long = DatabaseFactory.dbQuery {
@@ -1,30 +1,28 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import org.jetbrains.exposed.v1.core.Table
import org.jetbrains.exposed.v1.core.kotlin.datetime.datetime
import org.jetbrains.exposed.v1.core.kotlin.datetime.CurrentDateTime
import org.jetbrains.exposed.v1.core.javaUUID
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
import org.jetbrains.exposed.v1.datetime.timestamp
/**
* Exposed-Tabellendefinition für die Land-Entität (Länderstammdaten).
*
* Diese Tabelle speichert alle Informationen zu Ländern/Nationen entsprechend
* der LandDefinition Domain-Entität.
* Exposed-Tabellendefinition für die Land-Entität.
*/
object LandTable : Table("land") {
val id = javaUUID("id").autoGenerate()
val isoAlpha2Code = varchar("iso_alpha2_code", 2).uniqueIndex()
val isoAlpha3Code = varchar("iso_alpha3_code", 3).uniqueIndex()
val isoNumerischerCode = varchar("iso_numerischer_code", 3).nullable()
val nameDeutsch = varchar("name_deutsch", 100)
val nameEnglisch = varchar("name_englisch", 100).nullable()
val wappenUrl = varchar("wappen_url", 500).nullable()
val istEuMitglied = bool("ist_eu_mitglied").nullable()
val istEwrMitglied = bool("ist_ewr_mitglied").nullable()
val istAktiv = bool("ist_aktiv").default(true)
val sortierReihenfolge = integer("sortier_reihenfolge").nullable()
val createdAt = datetime("created_at").defaultExpression(CurrentDateTime)
val updatedAt = datetime("updated_at").defaultExpression(CurrentDateTime)
val id = uuid("land_id")
val isoAlpha2Code = varchar("iso_alpha2_code", 2).uniqueIndex()
val isoAlpha3Code = varchar("iso_alpha3_code", 3).uniqueIndex()
val isoNumerischerCode = varchar("iso_numerischer_code", 3).nullable()
val nameDeutsch = varchar("name_deutsch", 100)
val nameEnglisch = varchar("name_englisch", 100).nullable()
val wappenUrl = varchar("wappen_url", 255).nullable()
val istEuMitglied = bool("ist_eu_mitglied").nullable()
val istEwrMitglied = bool("ist_ewr_mitglied").nullable()
val istAktiv = bool("ist_aktiv").default(true)
val sortierReihenfolge = integer("sortier_reihenfolge").nullable()
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
override val primaryKey = PrimaryKey(id)
}
@@ -2,28 +2,26 @@
package at.mocode.masterdata.infrastructure.persistence
import at.mocode.core.domain.model.PlatzTypE
import at.mocode.core.utils.database.DatabaseFactory
import at.mocode.masterdata.domain.model.Platz
import at.mocode.masterdata.domain.repository.PlatzRepository
import at.mocode.core.utils.database.DatabaseFactory
import org.jetbrains.exposed.v1.core.ResultRow
import org.jetbrains.exposed.v1.core.SortOrder
import org.jetbrains.exposed.v1.core.and
import org.jetbrains.exposed.v1.core.eq
import org.jetbrains.exposed.v1.core.like
import org.jetbrains.exposed.v1.jdbc.andWhere
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.Uuid
import kotlinx.datetime.Clock
import kotlinx.datetime.TimeZone
import kotlinx.datetime.toInstant
import kotlinx.datetime.toLocalDateTime
import org.jetbrains.exposed.sql.*
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
/**
* Implementierung des PlatzRepository für die Datenbankzugriffe.
*
* Diese Implementierung verwendet Exposed SQL für den Datenbankzugriff
* und mappt zwischen der Platz Domain-Entität und der PlatzTable.
* Exposed-basierte Implementierung des Platz-Repositorys.
*/
class PlatzRepositoryImpl : PlatzRepository {
/**
* Konvertiert eine Datenbankzeile in ein Domain-Objekt.
*/
private fun rowToPlatz(row: ResultRow): Platz {
return Platz(
id = row[PlatzTable.id],
@@ -34,8 +32,8 @@ class PlatzRepositoryImpl : PlatzRepository {
typ = PlatzTypE.valueOf(row[PlatzTable.typ]),
istAktiv = row[PlatzTable.istAktiv],
sortierReihenfolge = row[PlatzTable.sortierReihenfolge],
createdAt = row[PlatzTable.createdAt].toInstant(TimeZone.UTC),
updatedAt = row[PlatzTable.updatedAt].toInstant(TimeZone.UTC)
createdAt = row[PlatzTable.createdAt],
updatedAt = row[PlatzTable.updatedAt]
)
}
@@ -47,144 +45,102 @@ class PlatzRepositoryImpl : PlatzRepository {
override suspend fun findByTournament(turnierId: Uuid, activeOnly: Boolean, orderBySortierung: Boolean): List<Platz> = DatabaseFactory.dbQuery {
val query = PlatzTable.selectAll().where { PlatzTable.turnierId eq turnierId }
if (activeOnly) {
query.andWhere { PlatzTable.istAktiv eq true }
}
if (orderBySortierung) {
query.orderBy(PlatzTable.sortierReihenfolge to SortOrder.ASC, PlatzTable.name to SortOrder.ASC)
} else {
query.orderBy(PlatzTable.name to SortOrder.ASC)
}
query.map(::rowToPlatz)
}
override suspend fun findByName(searchTerm: String, turnierId: Uuid?, limit: Int): List<Platz> = DatabaseFactory.dbQuery {
val pattern = "%$searchTerm%"
val query = PlatzTable.selectAll().where { PlatzTable.name like pattern }
turnierId?.let {
query.andWhere { PlatzTable.turnierId eq it }
}
query.limit(limit)
.orderBy(PlatzTable.name to SortOrder.ASC)
.map(::rowToPlatz)
turnierId?.let { tid -> query.andWhere { PlatzTable.turnierId eq tid } }
query.limit(limit).map(::rowToPlatz)
}
override suspend fun findByType(typ: PlatzTypE, turnierId: Uuid?, activeOnly: Boolean): List<Platz> = DatabaseFactory.dbQuery {
val query = PlatzTable.selectAll().where { PlatzTable.typ eq typ.name }
turnierId?.let {
query.andWhere { PlatzTable.turnierId eq it }
}
turnierId?.let { tid -> query.andWhere { PlatzTable.turnierId eq tid } }
if (activeOnly) {
query.andWhere { PlatzTable.istAktiv eq true }
}
query.orderBy(PlatzTable.name to SortOrder.ASC)
.map(::rowToPlatz)
query.map(::rowToPlatz)
}
override suspend fun findByGroundType(boden: String, turnierId: Uuid?, activeOnly: Boolean): List<Platz> = DatabaseFactory.dbQuery {
val query = PlatzTable.selectAll().where { PlatzTable.boden eq boden }
turnierId?.let {
query.andWhere { PlatzTable.turnierId eq it }
}
turnierId?.let { tid -> query.andWhere { PlatzTable.turnierId eq tid } }
if (activeOnly) {
query.andWhere { PlatzTable.istAktiv eq true }
}
query.orderBy(PlatzTable.name to SortOrder.ASC)
.map(::rowToPlatz)
query.map(::rowToPlatz)
}
override suspend fun findByDimensions(dimension: String, turnierId: Uuid?, activeOnly: Boolean): List<Platz> = DatabaseFactory.dbQuery {
val query = PlatzTable.selectAll().where { PlatzTable.dimension eq dimension }
turnierId?.let {
query.andWhere { PlatzTable.turnierId eq it }
}
turnierId?.let { tid -> query.andWhere { PlatzTable.turnierId eq tid } }
if (activeOnly) {
query.andWhere { PlatzTable.istAktiv eq true }
}
query.orderBy(PlatzTable.name to SortOrder.ASC)
.map(::rowToPlatz)
query.map(::rowToPlatz)
}
override suspend fun findAllActive(orderBySortierung: Boolean): List<Platz> = DatabaseFactory.dbQuery {
val query = PlatzTable.selectAll().where { PlatzTable.istAktiv eq true }
if (orderBySortierung) {
query.orderBy(PlatzTable.sortierReihenfolge to SortOrder.ASC, PlatzTable.name to SortOrder.ASC)
} else {
query.orderBy(PlatzTable.name to SortOrder.ASC)
}
query.map(::rowToPlatz)
}
override suspend fun findSuitableForDiscipline(
requiredType: PlatzTypE,
requiredDimensions: String?,
turnierId: Uuid?
): List<Platz> = DatabaseFactory.dbQuery {
val query = PlatzTable.selectAll().where {
(PlatzTable.typ eq requiredType.name) and (PlatzTable.istAktiv eq true)
}
requiredDimensions?.let { dimensions ->
query.andWhere { PlatzTable.dimension eq dimensions }
}
turnierId?.let {
query.andWhere { PlatzTable.turnierId eq it }
}
query.orderBy(PlatzTable.sortierReihenfolge to SortOrder.ASC, PlatzTable.name to SortOrder.ASC)
.map(::rowToPlatz)
override suspend fun findSuitableForDiscipline(
requiredType: PlatzTypE,
requiredDimensions: String?,
turnierId: Uuid?
): List<Platz> = DatabaseFactory.dbQuery {
val query = PlatzTable.selectAll().where { PlatzTable.typ eq requiredType.name }
requiredDimensions?.let { dim -> query.andWhere { PlatzTable.dimension eq dim } }
turnierId?.let { tid -> query.andWhere { PlatzTable.turnierId eq tid } }
query.andWhere { PlatzTable.istAktiv eq true }
query.map(::rowToPlatz)
}
override suspend fun save(platz: Platz): Platz = DatabaseFactory.dbQuery {
val now = Clock.System.now()
val existingPlatz = PlatzTable.selectAll().where { PlatzTable.id eq platz.id }.singleOrNull()
if (existingPlatz == null) {
// Insert a new venue
PlatzTable.insert { stmt ->
stmt[id] = platz.id
stmt[turnierId] = platz.turnierId
stmt[name] = platz.name
stmt[dimension] = platz.dimension
stmt[boden] = platz.boden
stmt[typ] = platz.typ.name
stmt[istAktiv] = platz.istAktiv
stmt[sortierReihenfolge] = platz.sortierReihenfolge
stmt[createdAt] = platz.createdAt.toLocalDateTime(TimeZone.UTC)
stmt[updatedAt] = now.toLocalDateTime(TimeZone.UTC)
val exists = PlatzTable.selectAll().where { PlatzTable.id eq platz.id }.any()
if (exists) {
PlatzTable.update({ PlatzTable.id eq platz.id }) {
it[turnierId] = platz.turnierId
it[name] = platz.name
it[dimension] = platz.dimension
it[boden] = platz.boden
it[typ] = platz.typ.name
it[istAktiv] = platz.istAktiv
it[sortierReihenfolge] = platz.sortierReihenfolge
it[updatedAt] = platz.updatedAt
}
platz
} else {
// Update existing venue
PlatzTable.update({ PlatzTable.id eq platz.id }) { stmt ->
stmt[turnierId] = platz.turnierId
stmt[name] = platz.name
stmt[dimension] = platz.dimension
stmt[boden] = platz.boden
stmt[typ] = platz.typ.name
stmt[istAktiv] = platz.istAktiv
stmt[sortierReihenfolge] = platz.sortierReihenfolge
stmt[updatedAt] = now.toLocalDateTime(TimeZone.UTC)
PlatzTable.insert {
it[id] = platz.id
it[turnierId] = platz.turnierId
it[name] = platz.name
it[dimension] = platz.dimension
it[boden] = platz.boden
it[typ] = platz.typ.name
it[istAktiv] = platz.istAktiv
it[sortierReihenfolge] = platz.sortierReihenfolge
it[createdAt] = platz.createdAt
it[updatedAt] = platz.updatedAt
}
platz
}
platz.copy(updatedAt = now)
}
override suspend fun delete(id: Uuid): Boolean = DatabaseFactory.dbQuery {
@@ -192,40 +148,24 @@ class PlatzRepositoryImpl : PlatzRepository {
}
override suspend fun existsByNameAndTournament(name: String, turnierId: Uuid): Boolean = DatabaseFactory.dbQuery {
PlatzTable.selectAll().where {
(PlatzTable.name eq name) and (PlatzTable.turnierId eq turnierId)
}.count() > 0
PlatzTable.selectAll().where { (PlatzTable.name eq name) and (PlatzTable.turnierId eq turnierId) }.any()
}
override suspend fun countActiveByTournament(turnierId: Uuid): Long = DatabaseFactory.dbQuery {
PlatzTable.selectAll().where {
(PlatzTable.turnierId eq turnierId) and (PlatzTable.istAktiv eq true)
}.count()
PlatzTable.selectAll().where { (PlatzTable.turnierId eq turnierId) and (PlatzTable.istAktiv eq true) }.count()
}
override suspend fun countByTypeAndTournament(typ: PlatzTypE, turnierId: Uuid, activeOnly: Boolean): Long = DatabaseFactory.dbQuery {
val query = PlatzTable.selectAll().where {
(PlatzTable.typ eq typ.name) and (PlatzTable.turnierId eq turnierId)
}
val query = PlatzTable.selectAll().where { (PlatzTable.turnierId eq turnierId) and (PlatzTable.typ eq typ.name) }
if (activeOnly) {
query.andWhere { PlatzTable.istAktiv eq true }
}
query.count()
}
override suspend fun findAvailableForTimeSlot(turnierId: Uuid, startTime: String?, endTime: String?): List<Platz> = DatabaseFactory.dbQuery {
// For now, this returns all active venues for the tournament
// This can be extended when venue scheduling functionality is implemented
val query = PlatzTable.selectAll().where {
(PlatzTable.turnierId eq turnierId) and (PlatzTable.istAktiv eq true)
}
// TODO: Add time slot availability logic when scheduling is implemented
// This would involve joining with a scheduling/booking table to check availability
query.orderBy(PlatzTable.sortierReihenfolge to SortOrder.ASC, PlatzTable.name to SortOrder.ASC)
// Derzeit gibt die Methode einfach alle aktiven Plätze des Turniers zurück.
PlatzTable.selectAll().where { (PlatzTable.turnierId eq turnierId) and (PlatzTable.istAktiv eq true) }
.map(::rowToPlatz)
}
}
@@ -1,38 +1,29 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import org.jetbrains.exposed.v1.core.Table
import org.jetbrains.exposed.v1.core.kotlin.datetime.datetime
import org.jetbrains.exposed.v1.core.kotlin.datetime.CurrentDateTime
import org.jetbrains.exposed.v1.core.javaUUID
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
import org.jetbrains.exposed.v1.datetime.timestamp
/**
* Exposed-Tabellendefinition für die Platz-Entität (Turnierplätze/Wettkampfstätten).
*
* Diese Tabelle speichert alle Informationen zu Plätzen und Arenen
* entsprechend der Platz Domain-Entität.
* Exposed-Tabellendefinition für die Platz-Entität.
*/
object PlatzTable : Table("platz") {
val id = javaUUID("id").autoGenerate()
val turnierId = javaUUID("turnier_id") // Foreign key to tournament (not enforced here as tournament might be in different module)
val name = varchar("name", 200)
val dimension = varchar("dimension", 50).nullable()
val boden = varchar("boden", 100).nullable()
val typ = varchar("typ", 50) // Enum as string
val istAktiv = bool("ist_aktiv").default(true)
val sortierReihenfolge = integer("sortier_reihenfolge").nullable()
val createdAt = datetime("created_at").defaultExpression(CurrentDateTime)
val updatedAt = datetime("updated_at").defaultExpression(CurrentDateTime)
val id = uuid("platz_id")
val turnierId = uuid("turnier_id")
val name = varchar("name", 100)
val dimension = varchar("dimension", 50).nullable()
val boden = varchar("boden", 50).nullable()
val typ = varchar("typ", 50)
val istAktiv = bool("ist_aktiv").default(true)
val sortierReihenfolge = integer("sortier_reihenfolge").nullable()
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
override val primaryKey = PrimaryKey(id)
init {
// Index for performance on common queries
index(customIndexName = "idx_platz_turnier", columns = arrayOf(turnierId))
index(customIndexName = "idx_platz_aktiv", columns = arrayOf(istAktiv))
index(customIndexName = "idx_platz_typ", columns = arrayOf(typ))
index(customIndexName = "idx_platz_turnier_aktiv", columns = arrayOf(turnierId, istAktiv))
// Unique constraint for name per tournament
uniqueIndex("uk_platz_name_turnier", name, turnierId)
}
init {
index("idx_platz_turnier", isUnique = false, turnierId)
}
}
@@ -0,0 +1,40 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import org.jetbrains.exposed.v1.core.Table
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
import org.jetbrains.exposed.v1.datetime.date
import org.jetbrains.exposed.v1.datetime.timestamp
/**
* Exposed-Tabellendefinition für die Reiter-Entität.
*/
object ReiterTable : Table("reiter") {
val id = uuid("reiter_id")
val personId = uuid("person_id")
val satznummer = varchar("satznummer", 10).uniqueIndex()
val lizenzNummer = varchar("lizenz_nummer", 20).nullable()
val lizenzKlasse = varchar("lizenz_klasse", 20)
val startkartAktiv = bool("startkart_aktiv").default(false)
val startkartSaison = integer("startkart_saison").nullable()
val feiId = varchar("fei_id", 20).nullable()
val nation = varchar("nation", 3).nullable()
val nachname = varchar("nachname", 100)
val vorname = varchar("vorname", 100)
val geburtsdatum = date("geburtsdatum").nullable()
val vereinsNummer = varchar("vereins_nummer", 10).nullable()
val vereinsName = varchar("vereins_name", 200).nullable()
val istGastreiter = bool("ist_gastreiter").default(false)
val istAktiv = bool("ist_aktiv").default(true)
val datenQuelle = varchar("daten_quelle", 50)
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
init {
index("idx_reiter_satznummer", isUnique = true, satznummer)
index("idx_reiter_name", isUnique = false, nachname, vorname)
}
}
@@ -0,0 +1,33 @@
@file:OptIn(kotlin.uuid.ExperimentalUuidApi::class)
package at.mocode.masterdata.infrastructure.persistence
import org.jetbrains.exposed.v1.core.Table
import org.jetbrains.exposed.v1.datetime.CurrentTimestamp
import org.jetbrains.exposed.v1.datetime.timestamp
/**
* Exposed-Tabellendefinition für die Verein-Entität.
*/
object VereinTable : Table("verein") {
val id = uuid("verein_id")
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 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)
val istAktiv = bool("ist_aktiv").default(true)
val bemerkungen = text("bemerkungen").nullable()
val datenQuelle = varchar("daten_quelle", 50)
val createdAt = timestamp("created_at").defaultExpression(CurrentTimestamp)
val updatedAt = timestamp("updated_at").defaultExpression(CurrentTimestamp)
override val primaryKey = PrimaryKey(id)
}