diff --git a/backend/services/entries/entries-service/src/main/kotlin/at/mocode/entries/service/bewerbe/BewerbRepositoryImpl.kt b/backend/services/entries/entries-service/src/main/kotlin/at/mocode/entries/service/bewerbe/BewerbRepositoryImpl.kt index bd80b56f..4a2c7e44 100644 --- a/backend/services/entries/entries-service/src/main/kotlin/at/mocode/entries/service/bewerbe/BewerbRepositoryImpl.kt +++ b/backend/services/entries/entries-service/src/main/kotlin/at/mocode/entries/service/bewerbe/BewerbRepositoryImpl.kt @@ -2,7 +2,11 @@ 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.BewerbRichterEinsatzTable import at.mocode.entries.service.persistence.BewerbTable import at.mocode.entries.service.tenant.tenantTransaction import org.jetbrains.exposed.v1.core.ResultRow @@ -18,25 +22,92 @@ import kotlin.uuid.toKotlinUuid class BewerbRepositoryImpl : BewerbRepository { - private fun rowToBewerb(row: ResultRow): Bewerb = Bewerb( - id = row[BewerbTable.id].toKotlinUuid(), - turnierId = row[BewerbTable.turnierId].toKotlinUuid(), - klasse = row[BewerbTable.klasse], - hoeheCm = row[BewerbTable.hoeheCm], - bezeichnung = row[BewerbTable.bezeichnung] - ) + private fun loadRichterEinsaetze(bewerbId: Uuid): List = + BewerbRichterEinsatzTable + .selectAll() + .where { BewerbRichterEinsatzTable.bewerbId eq bewerbId.toJavaUuid() } + .map { row -> + RichterEinsatz( + funktionaerId = row[BewerbRichterEinsatzTable.funktionaerId].toKotlinUuid(), + position = row[BewerbRichterEinsatzTable.position] + ) + } + + private fun persistRichterEinsaetze(bewerbId: Uuid, einsaetze: List) { + 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 { val now = Clock.System.now() BewerbTable.insert { s -> - s[BewerbTable.id] = b.id.toJavaUuid() - s[BewerbTable.turnierId] = b.turnierId.toJavaUuid() - s[BewerbTable.klasse] = b.klasse - s[BewerbTable.hoeheCm] = b.hoeheCm - s[BewerbTable.bezeichnung] = b.bezeichnung - s[BewerbTable.createdAt] = now - s[BewerbTable.updatedAt] = now + s[BewerbTable.id] = b.id.toJavaUuid() + s[BewerbTable.turnierId] = b.turnierId.toJavaUuid() + s[BewerbTable.klasse] = b.klasse + s[BewerbTable.hoeheCm] = b.hoeheCm + s[BewerbTable.bezeichnung] = b.bezeichnung + // 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.createdAt] = now + s[BewerbTable.updatedAt] = now } + persistRichterEinsaetze(b.id, b.richterEinsaetze) 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 { val now = Clock.System.now() BewerbTable.update({ BewerbTable.id eq b.id.toJavaUuid() }) { s -> - s[BewerbTable.klasse] = b.klasse - s[BewerbTable.hoeheCm] = b.hoeheCm - s[BewerbTable.bezeichnung] = b.bezeichnung - s[BewerbTable.updatedAt] = now + s[BewerbTable.klasse] = b.klasse + s[BewerbTable.hoeheCm] = b.hoeheCm + s[BewerbTable.bezeichnung] = b.bezeichnung + // 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() } diff --git a/backend/services/entries/entries-service/src/main/kotlin/at/mocode/entries/service/bewerbe/BewerbService.kt b/backend/services/entries/entries-service/src/main/kotlin/at/mocode/entries/service/bewerbe/BewerbService.kt index 85195217..41662d01 100644 --- a/backend/services/entries/entries-service/src/main/kotlin/at/mocode/entries/service/bewerbe/BewerbService.kt +++ b/backend/services/entries/entries-service/src/main/kotlin/at/mocode/entries/service/bewerbe/BewerbService.kt @@ -6,6 +6,7 @@ import at.mocode.entries.domain.repository.NennungRepository import at.mocode.entries.service.errors.LockedException import at.mocode.entries.service.persistence.TurnierTable 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.jdbc.selectAll import kotlin.uuid.Uuid @@ -21,14 +22,35 @@ class BewerbService( 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") val b = Bewerb( id = Uuid.random(), turnierId = turnierId, - klasse = klasse, - hoeheCm = hoeheCm, - bezeichnung = bezeichnung + 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.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 update(id: Uuid, klasse: String, hoeheCm: Int?, bezeichnung: String): Bewerb { + suspend fun update(id: Uuid, req: UpdateBewerbRequest): Bewerb { val current = get(id) 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) {