Remove domain models and services related to Abteilung, AbteilungsRegelService, and Bewerb: cleanup unnecessary entities, validation logic, and tests across backend modules.

This commit is contained in:
2026-04-13 21:58:06 +02:00
parent 76d7019d30
commit fb1c1ee4ce
76 changed files with 1091 additions and 267 deletions
@@ -1,3 +1,7 @@
@file:OptIn(ExperimentalWasmDsl::class)
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.kotlinSerialization)
@@ -7,38 +11,31 @@ group = "at.mocode"
version = "1.0.0"
kotlin {
// Toolchain is now handled centrally in the root build.gradle.kts
val enableWasm = providers.gradleProperty("enableWasm").orNull == "true"
// JVM target for backend usage
jvm()
// JS target for frontend usage (Compose/Browser)
js {
js(IR) {
browser()
// no need for binaries.executable() in a library
}
// Optional Wasm target for browser clients
if (enableWasm) {
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
wasmJs {
browser()
}
wasmJs {
browser()
}
sourceSets {
commonMain {
dependencies {
implementation(libs.kotlinx.serialization.json)
implementation(projects.core.coreDomain)
}
commonMain.dependencies {
implementation(projects.core.coreDomain)
implementation(projects.core.coreUtils)
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.serialization.json)
}
commonTest {
dependencies {
implementation(libs.kotlin.test)
}
commonTest.dependencies {
implementation(kotlin("test"))
}
jvmTest.dependencies {
implementation(projects.platform.platformTesting)
}
}
}
@@ -78,7 +78,8 @@ data class NennungEinreichenRequest(
val zahlerId: Uuid? = null,
val startwunsch: StartwunschE = StartwunschE.KEIN_WUNSCH,
val istNachnennung: Boolean = false,
val bemerkungen: String? = null
val bemerkungen: String? = null,
val email: String? = null
)
/**
@@ -1,26 +1,43 @@
@file:OptIn(ExperimentalWasmDsl::class)
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
plugins {
alias(libs.plugins.kotlinMultiplatform)
alias(libs.plugins.kotlinSerialization)
}
kotlin {
jvm()
js(IR) {
browser()
}
wasmJs {
browser()
}
sourceSets {
commonMain {
kotlin.srcDir("src/main/kotlin")
dependencies {
implementation(projects.core.coreDomain)
implementation(projects.core.coreUtils)
implementation(projects.backend.services.masterdata.masterdataDomain)
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.serialization.json)
}
all {
languageSettings.optIn("kotlin.uuid.ExperimentalUuidApi")
}
commonTest {
kotlin.srcDir("src/test/kotlin")
dependencies {
implementation(kotlin("test"))
implementation(projects.platform.platformTesting)
}
commonMain.dependencies {
implementation(projects.core.coreDomain)
implementation(projects.core.coreUtils)
implementation(projects.backend.services.masterdata.masterdataDomain)
implementation(libs.kotlinx.datetime)
implementation(libs.kotlinx.serialization.json)
}
commonTest.dependencies {
implementation(kotlin("test"))
}
jvmTest.dependencies {
implementation(projects.platform.platformTesting)
}
}
}
@@ -27,8 +27,10 @@ dependencies {
implementation(libs.bundles.spring.boot.secure.service)
// Common service extras
implementation(libs.spring.boot.starter.validation)
implementation(libs.spring.boot.starter.mail)
// JSON + Web: ensure Spring Web (incl. HttpMessageConverters) is on the classpath
implementation("org.springframework.boot:spring-boot-starter-web")
//implementation("org.springframework.boot:spring-boot-starter-web")
implementation(libs.spring.boot.starter.web)
implementation(libs.spring.boot.starter.json)
implementation(libs.postgresql.driver)
@@ -40,7 +42,8 @@ dependencies {
implementation(libs.caffeine)
// spring-web is included via spring-boot-starter-web above; keep explicit add if alias resolves elsewhere
// JDBC for JdbcTemplate-based TenantRegistry
implementation("org.springframework.boot:spring-boot-starter-jdbc")
//implementation("org.springframework.boot:spring-boot-starter-jdbc")
implementation(libs.spring.boot.starter.jdbc)
// Resilience Dependencies (manuell aufgelöst)
implementation(libs.resilience4j.spring.boot3)
@@ -55,10 +58,15 @@ dependencies {
// Flyway runtime (provided by BOM, ensure availability in this module)
implementation(libs.flyway.core)
implementation(libs.flyway.postgresql)
implementation(project(":core:zns-parser"))
//implementation(project(":core:zns-parser"))
implementation(projects.core.znsParser)
testImplementation(projects.platform.platformTesting)
testImplementation(libs.bundles.testing.jvm)
testImplementation(libs.spring.boot.starter.test)
testImplementation("com.h2database:h2")
//testImplementation("com.h2database:h2")
testImplementation(libs.h2.driver)
// testImplementation(libs.junit.jupiter.api)
// testImplementation(libs.junit.jupiter.engine)
}
@@ -0,0 +1,46 @@
package at.mocode.entries.service.notification
import org.slf4j.LoggerFactory
import org.springframework.mail.SimpleMailMessage
import org.springframework.mail.javamail.JavaMailSender
import org.springframework.stereotype.Service
@Service
class MailService(
private val mailSender: JavaMailSender? = null
) {
private val log = LoggerFactory.getLogger(MailService::class.java)
fun sendNennungsBestätigung(email: String, reiterName: String, turnierName: String, bewerbe: String) {
val subject = "Bestätigung Ihrer Online-Nennung: $turnierName"
val text = """
Hallo $reiterName,
vielen Dank für deine Nennung zum Turnier '$turnierName'.
Angemeldete Bewerbe: $bewerbe
Du kannst deine aktuelle Rechnung jederzeit online in deinem Teilnehmer-Konto einsehen und herunterladen.
Viel Erfolg beim Turnier!
Deine Meldestelle
""".trimIndent()
if (mailSender != null) {
try {
val message = SimpleMailMessage()
message.setTo(email)
message.setSubject(subject)
message.setText(text)
message.setFrom("noreply@mo-code.at")
mailSender.send(message)
log.info("Bestätigungs-Email an $email gesendet.")
} catch (e: Exception) {
log.error("Fehler beim Senden der Email an $email: ${e.message}")
}
} else {
log.warn("JavaMailSender nicht konfiguriert. Email-Versand übersprungen (Simulation).")
log.info("SIMULATION - Email an $email:\nSubject: $subject\nContent:\n$text")
}
}
}
@@ -4,6 +4,7 @@ package at.mocode.entries.service.usecase
import at.mocode.billing.domain.model.BuchungsTyp
import at.mocode.billing.service.TeilnehmerKontoService
import at.mocode.entries.service.notification.MailService
import at.mocode.core.domain.model.NennStatusE
import at.mocode.entries.api.*
import at.mocode.entries.domain.model.Nennung
@@ -28,7 +29,8 @@ class NennungUseCases(
private val nennungRepository: NennungRepository,
private val transferRepository: NennungsTransferRepository,
private val bewerbRepository: BewerbRepository,
private val kontoService: TeilnehmerKontoService
private val kontoService: TeilnehmerKontoService,
private val mailService: MailService
) {
private val log = LoggerFactory.getLogger(NennungUseCases::class.java)
@@ -115,6 +117,17 @@ class NennungUseCases(
}
}
// Bestätigungs-Email senden
val emailAddress = request.email
if (emailAddress != null) {
mailService.sendNennungsBestätigung(
email = emailAddress,
reiterName = "Reiter (ID: ${saved.reiterId})", // In einem echten System würden wir den Namen aus dem Person-Service laden
turnierName = "Turnier (ID: ${saved.turnierId})", // Analog für Turnier
bewerbe = bewerb?.let { "${it.bezeichnung} (${it.klasse})" } ?: "Unbekannter Bewerb"
)
}
return saved.toDetailDto()
}
@@ -7,6 +7,7 @@ import at.mocode.billing.service.TeilnehmerKontoService
import at.mocode.entries.api.NennungEinreichenRequest
import at.mocode.entries.service.bewerbe.Bewerb
import at.mocode.entries.service.bewerbe.BewerbRepository
import at.mocode.entries.service.notification.MailService
import at.mocode.entries.service.persistence.AbteilungTable
import at.mocode.entries.service.persistence.BewerbRichterEinsatzTable
import at.mocode.entries.service.persistence.BewerbTable
@@ -38,6 +39,9 @@ class NennungBillingIntegrationTest {
@Autowired
private lateinit var kontoService: TeilnehmerKontoService
@Autowired
private lateinit var mailService: MailService
private val turnierId = Uuid.random()
private val reiterId = Uuid.random()
private val pferdId = Uuid.random()
@@ -105,6 +109,38 @@ class NennungBillingIntegrationTest {
assertEquals(-2500L, buchungen[0].betragCent)
}
@Test
fun `nennung einreichen mit Email triggert MailService`() = kotlinx.coroutines.runBlocking {
// GIVEN
val bewerb = bewerbRepository.create(Bewerb(
id = Uuid.random(),
turnierId = turnierId,
klasse = "A",
bezeichnung = "Einfacher Reiterwettbewerb",
nenngeldCent = 1000,
hoeheCm = 0
))
val email = "test@reiter.at"
val request = NennungEinreichenRequest(
turnierId = turnierId,
bewerbId = bewerb.id,
abteilungId = abteilungId,
reiterId = reiterId,
pferdId = pferdId,
email = email
)
// WHEN
nennungUseCases.nennungEinreichen(request)
// THEN: Wir prüfen nur ob es nicht kracht.
// In einem echten Test mit Mockito/MockK könnten wir prüfen:
// verify { mailService.sendNennungsBestätigung(email, any(), any(), any()) }
// Da MailService in Spring registriert ist und JavaMailSender null ist, loggt er nur.
assertNotNull(mailService)
}
@Test
fun `nachnennung bucht zusätzlich Nachnenngebühr`() = kotlinx.coroutines.runBlocking {
// GIVEN: Ein Bewerb mit Nenngeld und Nachnenngebühr