### feat: verbessere DI, Healthcheck-Logik und Reiter-API

- **Healthcheck:** Aktualisiere Dockerfile und konsolidiere Ports für konsistente Service-Gesundheitsprüfungen (8086 für Actuator, 8091 für API-Traffic).
- **ReiterRepository:** Implementiere `KtorReiterRepository` zur Nutzung der Backend-Stammdaten über API.
- **DI-Module:** Passe `ReiterModule` und `VereinFeatureModule` an, um den authentifizierten `apiClient` zu verwenden.
- **Masterdata-Service:** Synchronisiere Environment-Variablen und Konsul-Konfiguration mit aktualisierten Ports.
This commit is contained in:
2026-04-22 12:11:33 +02:00
parent e0b1ce8836
commit d4cc0eb77d
9 changed files with 146 additions and 23 deletions
@@ -0,0 +1,64 @@
package at.mocode.frontend.features.reiter.data
import at.mocode.frontend.core.network.ApiRoutes
import at.mocode.frontend.features.reiter.domain.Reiter
import at.mocode.frontend.features.reiter.domain.ReiterRepository
import io.ktor.client.*
import io.ktor.client.call.*
import io.ktor.client.request.*
import io.ktor.http.*
import kotlinx.serialization.Serializable
@Serializable
private data class ReiterDto(
val id: String,
val znsNummer: String,
val vorname: String,
val nachname: String,
val oepsNummer: String? = null,
val email: String? = null
)
class KtorReiterRepository(
private val client: HttpClient
) : ReiterRepository {
override suspend fun getReiter(): Result<List<Reiter>> = runCatching {
val response = client.get(ApiRoutes.Masterdata.REITER)
if (response.status.isSuccess()) {
response.body<List<ReiterDto>>().map { it.toDomain() }
} else emptyList()
}
override suspend fun searchReiter(query: String): Result<List<Reiter>> = runCatching {
val response = client.get("${ApiRoutes.Masterdata.REITER}/search") {
parameter("query", query)
}
if (response.status.isSuccess()) {
response.body<List<ReiterDto>>().map { it.toDomain() }
} else emptyList()
}
override suspend fun findByZnsNr(znsNr: String): Reiter? {
return runCatching {
val response = client.get("${ApiRoutes.Masterdata.REITER}/zns/$znsNr")
if (response.status.isSuccess()) {
response.body<ReiterDto>().toDomain()
} else null
}.getOrNull()
}
override suspend fun saveReiter(reiter: Reiter): Result<Reiter> = runCatching {
// TODO: Implementierung falls nötig, aktuell primär Read-Only für ZNS
reiter
}
private fun ReiterDto.toDomain() = Reiter(
id = id,
vorname = vorname,
nachname = nachname,
satznummer = znsNummer,
oepsNummer = oepsNummer,
email = email
)
}
@@ -1,11 +1,12 @@
package at.mocode.frontend.features.reiter.di
import at.mocode.frontend.features.reiter.data.FakeReiterRepository
import at.mocode.frontend.features.reiter.data.KtorReiterRepository
import at.mocode.frontend.features.reiter.domain.ReiterRepository
import at.mocode.frontend.features.reiter.presentation.ReiterViewModel
import org.koin.core.qualifier.named
import org.koin.dsl.module
val reiterModule = module {
single<ReiterRepository> { FakeReiterRepository() }
single<ReiterRepository> { KtorReiterRepository(get(named("apiClient"))) }
factory { ReiterViewModel(get<ReiterRepository>()) }
}
@@ -4,10 +4,11 @@ import at.mocode.frontend.features.verein.data.KtorVereinRepository
import at.mocode.frontend.features.verein.domain.VereinRepository
import at.mocode.frontend.features.verein.presentation.VereinViewModel
import org.koin.core.module.dsl.viewModelOf
import org.koin.core.qualifier.named
import org.koin.dsl.module
val vereinFeatureModule = module {
// Desktop-App nutzt nun das KtorVereinRepository (API) oder wir könnten ein SQLite Repository bauen
single<VereinRepository> { KtorVereinRepository(get()) }
// Desktop-App nutzt nun das KtorVereinRepository (API)
single<VereinRepository> { KtorVereinRepository(get(named("apiClient"))) }
viewModelOf(::VereinViewModel)
}