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:
@@ -1,3 +1,7 @@
|
||||
@file:OptIn(ExperimentalWasmDsl::class)
|
||||
|
||||
import org.jetbrains.kotlin.gradle.ExperimentalWasmDsl
|
||||
|
||||
/**
|
||||
* Dieses Modul kapselt die Gebühren-Logik und Abrechnungs-Features (Billing-Sync).
|
||||
*/
|
||||
@@ -13,11 +17,24 @@ version = "1.0.0"
|
||||
|
||||
kotlin {
|
||||
jvm()
|
||||
@OptIn(org.jetbrains.kotlin.gradle.ExperimentalWasmDsl::class)
|
||||
wasmJs {
|
||||
browser()
|
||||
|
||||
js(IR) {
|
||||
binaries.library()
|
||||
browser {
|
||||
testTask {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wasmJs {
|
||||
binaries.library()
|
||||
browser {
|
||||
testTask {
|
||||
enabled = false
|
||||
}
|
||||
}
|
||||
}
|
||||
sourceSets {
|
||||
commonMain.dependencies {
|
||||
implementation(projects.frontend.core.designSystem)
|
||||
|
||||
+4
@@ -42,4 +42,8 @@ class DefaultBillingRepository(
|
||||
override suspend fun getRechnungPdf(kontoId: String): Result<ByteArray> = runCatching {
|
||||
client.get(ApiRoutes.Billing.rechnung(kontoId)).body()
|
||||
}
|
||||
|
||||
override suspend fun getOffenePosten(veranstaltungId: String): Result<List<TeilnehmerKontoDto>> = runCatching {
|
||||
client.get(ApiRoutes.Billing.offenePosten(veranstaltungId)).body()
|
||||
}
|
||||
}
|
||||
|
||||
+4
@@ -61,4 +61,8 @@ class FakeBillingRepository : BillingRepository {
|
||||
override suspend fun getRechnungPdf(kontoId: String): Result<ByteArray> {
|
||||
return Result.success("MOCK PDF CONTENT".encodeToByteArray())
|
||||
}
|
||||
|
||||
override suspend fun getOffenePosten(veranstaltungId: String): Result<List<TeilnehmerKontoDto>> {
|
||||
return Result.success(konten.filter { it.saldoCent < 0 })
|
||||
}
|
||||
}
|
||||
|
||||
+7
@@ -38,4 +38,11 @@ interface BillingRepository {
|
||||
suspend fun getRechnungPdf(
|
||||
kontoId: String
|
||||
): Result<ByteArray>
|
||||
|
||||
/**
|
||||
* Holt alle Konten mit negativem Saldo für eine Veranstaltung.
|
||||
*/
|
||||
suspend fun getOffenePosten(
|
||||
veranstaltungId: String
|
||||
): Result<List<TeilnehmerKontoDto>>
|
||||
}
|
||||
|
||||
+38
-4
@@ -37,7 +37,34 @@ fun BillingScreen(
|
||||
Spacer(Modifier.width(8.dp))
|
||||
Text("Teilnehmer-Abrechnung", style = MaterialTheme.typography.headlineSmall)
|
||||
Spacer(Modifier.weight(1f))
|
||||
IconButton(onClick = { viewModel.loadKonten(veranstaltungId.toString()) }) {
|
||||
|
||||
FilterChip(
|
||||
selected = !state.isOffenePostenMode,
|
||||
onClick = { viewModel.loadKonten(veranstaltungId.toString()) },
|
||||
label = { Text("Alle") },
|
||||
leadingIcon = if (!state.isOffenePostenMode) {
|
||||
{ Icon(Icons.Default.People, contentDescription = null, modifier = Modifier.size(18.dp)) }
|
||||
} else null
|
||||
)
|
||||
Spacer(Modifier.width(8.dp))
|
||||
FilterChip(
|
||||
selected = state.isOffenePostenMode,
|
||||
onClick = { viewModel.loadOffenePosten(veranstaltungId.toString()) },
|
||||
label = { Text("Offen") },
|
||||
leadingIcon = if (state.isOffenePostenMode) {
|
||||
{ Icon(Icons.Default.Warning, contentDescription = null, modifier = Modifier.size(18.dp), tint = MaterialTheme.colorScheme.error) }
|
||||
} else null,
|
||||
colors = FilterChipDefaults.filterChipColors(
|
||||
selectedContainerColor = MaterialTheme.colorScheme.errorContainer,
|
||||
selectedLabelColor = MaterialTheme.colorScheme.error
|
||||
)
|
||||
)
|
||||
|
||||
Spacer(Modifier.width(16.dp))
|
||||
IconButton(onClick = {
|
||||
if (state.isOffenePostenMode) viewModel.loadOffenePosten(veranstaltungId.toString())
|
||||
else viewModel.loadKonten(veranstaltungId.toString())
|
||||
}) {
|
||||
Icon(Icons.Default.Refresh, contentDescription = "Aktualisieren")
|
||||
}
|
||||
}
|
||||
@@ -51,15 +78,22 @@ fun BillingScreen(
|
||||
elevation = CardDefaults.cardElevation(defaultElevation = 2.dp)
|
||||
) {
|
||||
Column(modifier = Modifier.padding(8.dp)) {
|
||||
Text("Teilnehmer", fontWeight = FontWeight.Bold, fontSize = 14.sp)
|
||||
Text(
|
||||
if (state.isOffenePostenMode) "Offene Posten" else "Teilnehmer",
|
||||
fontWeight = FontWeight.Bold,
|
||||
fontSize = 14.sp,
|
||||
color = if (state.isOffenePostenMode) MaterialTheme.colorScheme.error else Color.Unspecified
|
||||
)
|
||||
HorizontalDivider(Modifier.padding(vertical = 4.dp))
|
||||
|
||||
if (state.isLoading && state.konten.isEmpty()) {
|
||||
if (state.isLoading && (state.konten.isEmpty() && state.offenePosten.isEmpty())) {
|
||||
CircularProgressIndicator(modifier = Modifier.align(Alignment.CenterHorizontally).padding(16.dp))
|
||||
}
|
||||
|
||||
val displayList = if (state.isOffenePostenMode) state.offenePosten else state.konten
|
||||
|
||||
LazyColumn {
|
||||
items(state.konten) { konto ->
|
||||
items(displayList) { konto ->
|
||||
KontoItem(
|
||||
konto = konto,
|
||||
isSelected = state.selectedKonto?.id == konto.id,
|
||||
|
||||
+19
-1
@@ -16,6 +16,8 @@ data class BillingUiState(
|
||||
val konten: List<TeilnehmerKontoDto> = emptyList(),
|
||||
val selectedKonto: TeilnehmerKontoDto? = null,
|
||||
val buchungen: List<BuchungDto> = emptyList(),
|
||||
val offenePosten: List<TeilnehmerKontoDto> = emptyList(),
|
||||
val isOffenePostenMode: Boolean = false,
|
||||
val pdfData: ByteArray? = null,
|
||||
val error: String? = null
|
||||
)
|
||||
@@ -29,7 +31,7 @@ class BillingViewModel(
|
||||
|
||||
fun loadKonten(veranstaltungId: String) {
|
||||
viewModelScope.launch {
|
||||
_uiState.value = _uiState.value.copy(isLoading = true, error = null)
|
||||
_uiState.value = _uiState.value.copy(isLoading = true, error = null, isOffenePostenMode = false)
|
||||
try {
|
||||
repository.getKonten(veranstaltungId)
|
||||
.onSuccess { konten ->
|
||||
@@ -50,6 +52,22 @@ class BillingViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun loadOffenePosten(veranstaltungId: String) {
|
||||
viewModelScope.launch {
|
||||
_uiState.value = _uiState.value.copy(isLoading = true, error = null, isOffenePostenMode = true)
|
||||
repository.getOffenePosten(veranstaltungId)
|
||||
.onSuccess { konten ->
|
||||
_uiState.value = _uiState.value.copy(offenePosten = konten, isLoading = false, error = null)
|
||||
}
|
||||
.onFailure {
|
||||
_uiState.value = _uiState.value.copy(
|
||||
isLoading = false,
|
||||
error = "Fehler beim Laden der offenen Posten: ${it.message ?: "Unbekannter Fehler"}"
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fun loadKonto(veranstaltungId: String, personId: String, personName: String) {
|
||||
viewModelScope.launch {
|
||||
_uiState.value = _uiState.value.copy(isLoading = true, error = null)
|
||||
|
||||
Reference in New Issue
Block a user