Extend Bewerb repository and service: add RichterEinsatz handling, enhance property mapping, and align DTOs with updated domain model.
This commit is contained in:
+110
-18
@@ -2,7 +2,11 @@
|
|||||||
|
|
||||||
package at.mocode.entries.service.bewerbe
|
package at.mocode.entries.service.bewerbe
|
||||||
|
|
||||||
|
import at.mocode.core.domain.model.AbteilungsTeilungsTypE
|
||||||
|
import at.mocode.core.domain.model.BeginnZeitTypE
|
||||||
|
import at.mocode.entries.domain.model.RichterEinsatz
|
||||||
import at.mocode.entries.service.persistence.AbteilungTable
|
import at.mocode.entries.service.persistence.AbteilungTable
|
||||||
|
import at.mocode.entries.service.persistence.BewerbRichterEinsatzTable
|
||||||
import at.mocode.entries.service.persistence.BewerbTable
|
import at.mocode.entries.service.persistence.BewerbTable
|
||||||
import at.mocode.entries.service.tenant.tenantTransaction
|
import at.mocode.entries.service.tenant.tenantTransaction
|
||||||
import org.jetbrains.exposed.v1.core.ResultRow
|
import org.jetbrains.exposed.v1.core.ResultRow
|
||||||
@@ -18,25 +22,92 @@ import kotlin.uuid.toKotlinUuid
|
|||||||
|
|
||||||
class BewerbRepositoryImpl : BewerbRepository {
|
class BewerbRepositoryImpl : BewerbRepository {
|
||||||
|
|
||||||
private fun rowToBewerb(row: ResultRow): Bewerb = Bewerb(
|
private fun loadRichterEinsaetze(bewerbId: Uuid): List<RichterEinsatz> =
|
||||||
id = row[BewerbTable.id].toKotlinUuid(),
|
BewerbRichterEinsatzTable
|
||||||
turnierId = row[BewerbTable.turnierId].toKotlinUuid(),
|
.selectAll()
|
||||||
klasse = row[BewerbTable.klasse],
|
.where { BewerbRichterEinsatzTable.bewerbId eq bewerbId.toJavaUuid() }
|
||||||
hoeheCm = row[BewerbTable.hoeheCm],
|
.map { row ->
|
||||||
bezeichnung = row[BewerbTable.bezeichnung]
|
RichterEinsatz(
|
||||||
)
|
funktionaerId = row[BewerbRichterEinsatzTable.funktionaerId].toKotlinUuid(),
|
||||||
|
position = row[BewerbRichterEinsatzTable.position]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun persistRichterEinsaetze(bewerbId: Uuid, einsaetze: List<RichterEinsatz>) {
|
||||||
|
BewerbRichterEinsatzTable.deleteWhere { BewerbRichterEinsatzTable.bewerbId eq bewerbId.toJavaUuid() }
|
||||||
|
einsaetze.forEach { re ->
|
||||||
|
BewerbRichterEinsatzTable.insert { s ->
|
||||||
|
s[BewerbRichterEinsatzTable.bewerbId] = bewerbId.toJavaUuid()
|
||||||
|
s[BewerbRichterEinsatzTable.funktionaerId] = re.funktionaerId.toJavaUuid()
|
||||||
|
s[BewerbRichterEinsatzTable.position] = re.position
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun rowToBewerb(row: ResultRow): Bewerb {
|
||||||
|
val id = row[BewerbTable.id].toKotlinUuid()
|
||||||
|
return Bewerb(
|
||||||
|
id = id,
|
||||||
|
turnierId = row[BewerbTable.turnierId].toKotlinUuid(),
|
||||||
|
klasse = row[BewerbTable.klasse],
|
||||||
|
hoeheCm = row[BewerbTable.hoeheCm],
|
||||||
|
bezeichnung = row[BewerbTable.bezeichnung],
|
||||||
|
// Abteilungs-Konfiguration
|
||||||
|
teilungsTyp = row[BewerbTable.teilungsTyp]?.let { AbteilungsTeilungsTypE.valueOf(it) },
|
||||||
|
// Text & Details
|
||||||
|
beschreibung = row[BewerbTable.beschreibung],
|
||||||
|
aufgabe = row[BewerbTable.aufgabe],
|
||||||
|
aufgabenNummer = row[BewerbTable.aufgabenNummer],
|
||||||
|
paraGrade = row[BewerbTable.paraGrade],
|
||||||
|
// Ort & Funktionäre
|
||||||
|
austragungsplatzId = row[BewerbTable.austragungsplatzId]?.toKotlinUuid(),
|
||||||
|
richterEinsaetze = loadRichterEinsaetze(id),
|
||||||
|
// Zeitplan – exposed-kotlin-datetime liefert kotlinx.datetime-Typen direkt
|
||||||
|
geplantesDatum = row[BewerbTable.geplantesDatum],
|
||||||
|
beginnZeitTyp = row[BewerbTable.beginnZeitTyp]?.let { BeginnZeitTypE.valueOf(it) },
|
||||||
|
beginnZeit = row[BewerbTable.beginnZeit],
|
||||||
|
reitdauerMinuten = row[BewerbTable.reitdauerMinuten],
|
||||||
|
umbauMinuten = row[BewerbTable.umbauMinuten],
|
||||||
|
besichtigungMinuten = row[BewerbTable.besichtigungMinuten],
|
||||||
|
stechenGeplant = row[BewerbTable.stechenGeplant],
|
||||||
|
// Finanzen
|
||||||
|
startgeldCent = row[BewerbTable.startgeldCent],
|
||||||
|
geldpreisAusbezahlt = row[BewerbTable.geldpreisAusbezahlt]
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override suspend fun create(b: Bewerb): Bewerb = tenantTransaction {
|
override suspend fun create(b: Bewerb): Bewerb = tenantTransaction {
|
||||||
val now = Clock.System.now()
|
val now = Clock.System.now()
|
||||||
BewerbTable.insert { s ->
|
BewerbTable.insert { s ->
|
||||||
s[BewerbTable.id] = b.id.toJavaUuid()
|
s[BewerbTable.id] = b.id.toJavaUuid()
|
||||||
s[BewerbTable.turnierId] = b.turnierId.toJavaUuid()
|
s[BewerbTable.turnierId] = b.turnierId.toJavaUuid()
|
||||||
s[BewerbTable.klasse] = b.klasse
|
s[BewerbTable.klasse] = b.klasse
|
||||||
s[BewerbTable.hoeheCm] = b.hoeheCm
|
s[BewerbTable.hoeheCm] = b.hoeheCm
|
||||||
s[BewerbTable.bezeichnung] = b.bezeichnung
|
s[BewerbTable.bezeichnung] = b.bezeichnung
|
||||||
s[BewerbTable.createdAt] = now
|
// Abteilungs-Konfiguration
|
||||||
s[BewerbTable.updatedAt] = now
|
s[BewerbTable.teilungsTyp] = b.teilungsTyp?.name
|
||||||
|
// Text & Details
|
||||||
|
s[BewerbTable.beschreibung] = b.beschreibung
|
||||||
|
s[BewerbTable.aufgabe] = b.aufgabe
|
||||||
|
s[BewerbTable.aufgabenNummer] = b.aufgabenNummer
|
||||||
|
s[BewerbTable.paraGrade] = b.paraGrade
|
||||||
|
// Ort
|
||||||
|
s[BewerbTable.austragungsplatzId] = b.austragungsplatzId?.toJavaUuid()
|
||||||
|
// Zeitplan – kotlinx.datetime-Typen direkt übergeben
|
||||||
|
s[BewerbTable.geplantesDatum] = b.geplantesDatum
|
||||||
|
s[BewerbTable.beginnZeitTyp] = b.beginnZeitTyp?.name
|
||||||
|
s[BewerbTable.beginnZeit] = b.beginnZeit
|
||||||
|
s[BewerbTable.reitdauerMinuten] = b.reitdauerMinuten
|
||||||
|
s[BewerbTable.umbauMinuten] = b.umbauMinuten
|
||||||
|
s[BewerbTable.besichtigungMinuten] = b.besichtigungMinuten
|
||||||
|
s[BewerbTable.stechenGeplant] = b.stechenGeplant
|
||||||
|
// Finanzen
|
||||||
|
s[BewerbTable.startgeldCent] = b.startgeldCent
|
||||||
|
s[BewerbTable.geldpreisAusbezahlt] = b.geldpreisAusbezahlt
|
||||||
|
s[BewerbTable.createdAt] = now
|
||||||
|
s[BewerbTable.updatedAt] = now
|
||||||
}
|
}
|
||||||
|
persistRichterEinsaetze(b.id, b.richterEinsaetze)
|
||||||
BewerbTable.selectAll().where { BewerbTable.id eq b.id.toJavaUuid() }.map(::rowToBewerb).single()
|
BewerbTable.selectAll().where { BewerbTable.id eq b.id.toJavaUuid() }.map(::rowToBewerb).single()
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -54,11 +125,32 @@ class BewerbRepositoryImpl : BewerbRepository {
|
|||||||
override suspend fun update(b: Bewerb): Bewerb = tenantTransaction {
|
override suspend fun update(b: Bewerb): Bewerb = tenantTransaction {
|
||||||
val now = Clock.System.now()
|
val now = Clock.System.now()
|
||||||
BewerbTable.update({ BewerbTable.id eq b.id.toJavaUuid() }) { s ->
|
BewerbTable.update({ BewerbTable.id eq b.id.toJavaUuid() }) { s ->
|
||||||
s[BewerbTable.klasse] = b.klasse
|
s[BewerbTable.klasse] = b.klasse
|
||||||
s[BewerbTable.hoeheCm] = b.hoeheCm
|
s[BewerbTable.hoeheCm] = b.hoeheCm
|
||||||
s[BewerbTable.bezeichnung] = b.bezeichnung
|
s[BewerbTable.bezeichnung] = b.bezeichnung
|
||||||
s[BewerbTable.updatedAt] = now
|
// Abteilungs-Konfiguration
|
||||||
|
s[BewerbTable.teilungsTyp] = b.teilungsTyp?.name
|
||||||
|
// Text & Details
|
||||||
|
s[BewerbTable.beschreibung] = b.beschreibung
|
||||||
|
s[BewerbTable.aufgabe] = b.aufgabe
|
||||||
|
s[BewerbTable.aufgabenNummer] = b.aufgabenNummer
|
||||||
|
s[BewerbTable.paraGrade] = b.paraGrade
|
||||||
|
// Ort
|
||||||
|
s[BewerbTable.austragungsplatzId] = b.austragungsplatzId?.toJavaUuid()
|
||||||
|
// Zeitplan – kotlinx.datetime-Typen direkt übergeben
|
||||||
|
s[BewerbTable.geplantesDatum] = b.geplantesDatum
|
||||||
|
s[BewerbTable.beginnZeitTyp] = b.beginnZeitTyp?.name
|
||||||
|
s[BewerbTable.beginnZeit] = b.beginnZeit
|
||||||
|
s[BewerbTable.reitdauerMinuten] = b.reitdauerMinuten
|
||||||
|
s[BewerbTable.umbauMinuten] = b.umbauMinuten
|
||||||
|
s[BewerbTable.besichtigungMinuten] = b.besichtigungMinuten
|
||||||
|
s[BewerbTable.stechenGeplant] = b.stechenGeplant
|
||||||
|
// Finanzen
|
||||||
|
s[BewerbTable.startgeldCent] = b.startgeldCent
|
||||||
|
s[BewerbTable.geldpreisAusbezahlt] = b.geldpreisAusbezahlt
|
||||||
|
s[BewerbTable.updatedAt] = now
|
||||||
}
|
}
|
||||||
|
persistRichterEinsaetze(b.id, b.richterEinsaetze)
|
||||||
BewerbTable.selectAll().where { BewerbTable.id eq b.id.toJavaUuid() }.map(::rowToBewerb).single()
|
BewerbTable.selectAll().where { BewerbTable.id eq b.id.toJavaUuid() }.map(::rowToBewerb).single()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+54
-6
@@ -6,6 +6,7 @@ import at.mocode.entries.domain.repository.NennungRepository
|
|||||||
import at.mocode.entries.service.errors.LockedException
|
import at.mocode.entries.service.errors.LockedException
|
||||||
import at.mocode.entries.service.persistence.TurnierTable
|
import at.mocode.entries.service.persistence.TurnierTable
|
||||||
import at.mocode.entries.service.tenant.tenantTransaction
|
import at.mocode.entries.service.tenant.tenantTransaction
|
||||||
|
import at.mocode.entries.domain.model.RichterEinsatz
|
||||||
import org.jetbrains.exposed.v1.core.eq
|
import org.jetbrains.exposed.v1.core.eq
|
||||||
import org.jetbrains.exposed.v1.jdbc.selectAll
|
import org.jetbrains.exposed.v1.jdbc.selectAll
|
||||||
import kotlin.uuid.Uuid
|
import kotlin.uuid.Uuid
|
||||||
@@ -21,14 +22,35 @@ class BewerbService(
|
|||||||
row?.get(TurnierTable.status) == "PUBLISHED"
|
row?.get(TurnierTable.status) == "PUBLISHED"
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun create(turnierId: Uuid, klasse: String, hoeheCm: Int?, bezeichnung: String): Bewerb {
|
suspend fun create(turnierId: Uuid, req: CreateBewerbRequest): Bewerb {
|
||||||
if (isTurnierPublished(turnierId)) throw LockedException("Turnier ist PUBLISHED – Bewerbe können nicht angelegt werden")
|
if (isTurnierPublished(turnierId)) throw LockedException("Turnier ist PUBLISHED – Bewerbe können nicht angelegt werden")
|
||||||
val b = Bewerb(
|
val b = Bewerb(
|
||||||
id = Uuid.random(),
|
id = Uuid.random(),
|
||||||
turnierId = turnierId,
|
turnierId = turnierId,
|
||||||
klasse = klasse,
|
klasse = req.klasse,
|
||||||
hoeheCm = hoeheCm,
|
hoeheCm = req.hoeheCm,
|
||||||
bezeichnung = bezeichnung
|
bezeichnung = req.bezeichnung,
|
||||||
|
// Abteilungs-Konfiguration
|
||||||
|
teilungsTyp = req.teilungsTyp,
|
||||||
|
// Text & Details
|
||||||
|
beschreibung = req.beschreibung,
|
||||||
|
aufgabe = req.aufgabe,
|
||||||
|
aufgabenNummer = req.aufgabenNummer,
|
||||||
|
paraGrade = req.paraGrade,
|
||||||
|
// Ort & Funktionäre
|
||||||
|
austragungsplatzId = req.austragungsplatzId?.let { Uuid.parse(it) },
|
||||||
|
richterEinsaetze = req.richterEinsaetze.map { RichterEinsatz(Uuid.parse(it.funktionaerId), it.position) },
|
||||||
|
// Zeitplan
|
||||||
|
geplantesDatum = req.geplantesDatum,
|
||||||
|
beginnZeitTyp = req.beginnZeitTyp,
|
||||||
|
beginnZeit = req.beginnZeit,
|
||||||
|
reitdauerMinuten = req.reitdauerMinuten,
|
||||||
|
umbauMinuten = req.umbauMinuten,
|
||||||
|
besichtigungMinuten = req.besichtigungMinuten,
|
||||||
|
stechenGeplant = req.stechenGeplant,
|
||||||
|
// Finanzen
|
||||||
|
startgeldCent = req.startgeldCent,
|
||||||
|
geldpreisAusbezahlt = req.geldpreisAusbezahlt
|
||||||
)
|
)
|
||||||
return repo.create(b)
|
return repo.create(b)
|
||||||
}
|
}
|
||||||
@@ -37,10 +59,36 @@ class BewerbService(
|
|||||||
|
|
||||||
suspend fun get(id: Uuid): Bewerb = repo.findById(id) ?: throw NoSuchElementException("Bewerb $id nicht gefunden")
|
suspend fun get(id: Uuid): Bewerb = repo.findById(id) ?: throw NoSuchElementException("Bewerb $id nicht gefunden")
|
||||||
|
|
||||||
suspend fun update(id: Uuid, klasse: String, hoeheCm: Int?, bezeichnung: String): Bewerb {
|
suspend fun update(id: Uuid, req: UpdateBewerbRequest): Bewerb {
|
||||||
val current = get(id)
|
val current = get(id)
|
||||||
if (isTurnierPublished(current.turnierId)) throw LockedException("Turnier ist PUBLISHED – Bewerbe können nicht geändert werden")
|
if (isTurnierPublished(current.turnierId)) throw LockedException("Turnier ist PUBLISHED – Bewerbe können nicht geändert werden")
|
||||||
return repo.update(current.copy(klasse = klasse, hoeheCm = hoeheCm, bezeichnung = bezeichnung))
|
val updated = current.copy(
|
||||||
|
klasse = req.klasse,
|
||||||
|
hoeheCm = req.hoeheCm,
|
||||||
|
bezeichnung = req.bezeichnung,
|
||||||
|
// Abteilungs-Konfiguration
|
||||||
|
teilungsTyp = req.teilungsTyp,
|
||||||
|
// Text & Details
|
||||||
|
beschreibung = req.beschreibung,
|
||||||
|
aufgabe = req.aufgabe,
|
||||||
|
aufgabenNummer = req.aufgabenNummer,
|
||||||
|
paraGrade = req.paraGrade,
|
||||||
|
// Ort & Funktionäre
|
||||||
|
austragungsplatzId = req.austragungsplatzId?.let { Uuid.parse(it) },
|
||||||
|
richterEinsaetze = req.richterEinsaetze.map { RichterEinsatz(Uuid.parse(it.funktionaerId), it.position) },
|
||||||
|
// Zeitplan
|
||||||
|
geplantesDatum = req.geplantesDatum,
|
||||||
|
beginnZeitTyp = req.beginnZeitTyp,
|
||||||
|
beginnZeit = req.beginnZeit,
|
||||||
|
reitdauerMinuten = req.reitdauerMinuten,
|
||||||
|
umbauMinuten = req.umbauMinuten,
|
||||||
|
besichtigungMinuten = req.besichtigungMinuten,
|
||||||
|
stechenGeplant = req.stechenGeplant,
|
||||||
|
// Finanzen
|
||||||
|
startgeldCent = req.startgeldCent,
|
||||||
|
geldpreisAusbezahlt = req.geldpreisAusbezahlt,
|
||||||
|
)
|
||||||
|
return repo.update(updated)
|
||||||
}
|
}
|
||||||
|
|
||||||
suspend fun delete(id: Uuid) {
|
suspend fun delete(id: Uuid) {
|
||||||
|
|||||||
Reference in New Issue
Block a user