Enhance billing logic: add REST support for manual and automated transactions, refine billing routes, adapt frontend API integration, and implement transaction type validation.
This commit is contained in:
+4
-8
@@ -16,28 +16,24 @@ class DefaultBillingRepository(
|
||||
personId: String,
|
||||
personName: String
|
||||
): Result<TeilnehmerKontoDto> = runCatching {
|
||||
client.get(ApiRoutes.Billing.KONTEN) {
|
||||
parameter("veranstaltungId", veranstaltungId)
|
||||
parameter("personId", personId)
|
||||
client.get(ApiRoutes.Billing.personKonto(veranstaltungId, personId)) {
|
||||
parameter("personName", personName)
|
||||
}.body()
|
||||
}
|
||||
|
||||
override suspend fun getKonten(veranstaltungId: String): Result<List<TeilnehmerKontoDto>> = runCatching {
|
||||
client.get(ApiRoutes.Billing.KONTEN) {
|
||||
parameter("veranstaltungId", veranstaltungId)
|
||||
}.body()
|
||||
client.get(ApiRoutes.Billing.veranstaltungKonten(veranstaltungId)).body()
|
||||
}
|
||||
|
||||
override suspend fun getBuchungen(kontoId: String): Result<List<BuchungDto>> = runCatching {
|
||||
client.get(ApiRoutes.Billing.buchungen(kontoId)).body()
|
||||
client.get(ApiRoutes.Billing.historie(kontoId)).body()
|
||||
}
|
||||
|
||||
override suspend fun addBuchung(
|
||||
kontoId: String,
|
||||
request: BuchungRequest
|
||||
): Result<TeilnehmerKontoDto> = runCatching {
|
||||
client.post(ApiRoutes.Billing.buchungen(kontoId)) {
|
||||
client.post(ApiRoutes.Billing.buche(kontoId)) {
|
||||
contentType(ContentType.Application.Json)
|
||||
setBody(request)
|
||||
}.body()
|
||||
|
||||
+1
-1
@@ -59,7 +59,7 @@ data class BuchungDto(
|
||||
data class BuchungRequest(
|
||||
val betragCent: Long,
|
||||
val verwendungszweck: String,
|
||||
val typ: String = "MANUELL"
|
||||
val typ: String // Pflichtfeld, muss mit Backend-Enum übereinstimmen
|
||||
)
|
||||
|
||||
enum class GebuehrTyp {
|
||||
|
||||
+27
-12
@@ -120,8 +120,8 @@ fun BillingScreen(
|
||||
if (showBuchungsDialog) {
|
||||
ManuelleBuchungDialog(
|
||||
onDismiss = { showBuchungsDialog = false },
|
||||
onConfirm = { betrag, zweck ->
|
||||
viewModel.buche(betrag, zweck)
|
||||
onConfirm = { betrag, zweck, typ ->
|
||||
viewModel.buche(betrag, zweck, typ)
|
||||
showBuchungsDialog = false
|
||||
}
|
||||
)
|
||||
@@ -179,28 +179,43 @@ private fun BuchungItem(buchung: BuchungDto) {
|
||||
@Composable
|
||||
private fun ManuelleBuchungDialog(
|
||||
onDismiss: () -> Unit,
|
||||
onConfirm: (Long, String) -> Unit
|
||||
onConfirm: (Long, String, String) -> Unit
|
||||
) {
|
||||
var betragStr by remember { mutableStateOf("") }
|
||||
var zweck by remember { mutableStateOf("") }
|
||||
var isGutschrift by remember { mutableStateOf(false) }
|
||||
var selectedTyp by remember { mutableStateOf("ZAHLUNG_BAR") }
|
||||
|
||||
val typen = listOf(
|
||||
"ZAHLUNG_BAR" to "Zahlung Bar",
|
||||
"ZAHLUNG_KARTE" to "Zahlung Karte",
|
||||
"GUTSCHRIFT" to "Gutschrift",
|
||||
"NENNGEBUEHR" to "Nenngebühr",
|
||||
"STARTGEBUEHR" to "Startgebühr",
|
||||
"BOXENGEBUEHR" to "Boxengebühr",
|
||||
"STORNIERUNG" to "Stornierung"
|
||||
)
|
||||
|
||||
AlertDialog(
|
||||
onDismissRequest = onDismiss,
|
||||
title = { Text("Manuelle Buchung") },
|
||||
text = {
|
||||
Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
RadioButton(selected = !isGutschrift, onClick = { isGutschrift = false })
|
||||
Text("Belastung (-)", modifier = Modifier.clickable { isGutschrift = false })
|
||||
Spacer(Modifier.width(16.dp))
|
||||
RadioButton(selected = isGutschrift, onClick = { isGutschrift = true })
|
||||
Text("Gutschrift (+)", modifier = Modifier.clickable { isGutschrift = true })
|
||||
Text("Buchungstyp:", style = MaterialTheme.typography.labelMedium)
|
||||
|
||||
// Einfache Auswahl via FlowRow oder Column (hier Column für Platz)
|
||||
Column {
|
||||
typen.forEach { (id, label) ->
|
||||
Row(verticalAlignment = Alignment.CenterVertically, modifier = Modifier.clickable { selectedTyp = id }) {
|
||||
RadioButton(selected = selectedTyp == id, onClick = { selectedTyp = id })
|
||||
Text(label, fontSize = 12.sp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OutlinedTextField(
|
||||
value = betragStr,
|
||||
onValueChange = { if (it.isEmpty() || it.toDoubleOrNull() != null) betragStr = it },
|
||||
label = { Text("Betrag in €") },
|
||||
label = { Text("Betrag in € (immer positiv eingeben)") },
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
singleLine = true
|
||||
)
|
||||
@@ -218,7 +233,7 @@ private fun ManuelleBuchungDialog(
|
||||
onClick = {
|
||||
val euro = betragStr.toDoubleOrNull() ?: 0.0
|
||||
val cent = (euro * 100).toLong()
|
||||
onConfirm(if (isGutschrift) cent else -cent, zweck)
|
||||
onConfirm(cent, zweck, selectedTyp)
|
||||
},
|
||||
enabled = betragStr.isNotEmpty() && zweck.isNotEmpty()
|
||||
) {
|
||||
|
||||
+2
-2
@@ -66,11 +66,11 @@ class BillingViewModel(
|
||||
}
|
||||
}
|
||||
|
||||
fun buche(betragCent: Long, zweck: String) {
|
||||
fun buche(betragCent: Long, zweck: String, typ: String) {
|
||||
val konto = _uiState.value.selectedKonto ?: return
|
||||
viewModelScope.launch {
|
||||
_uiState.value = _uiState.value.copy(isLoading = true)
|
||||
val request = BuchungRequest(betragCent = betragCent, verwendungszweck = zweck)
|
||||
val request = BuchungRequest(betragCent = betragCent, verwendungszweck = zweck, typ = typ)
|
||||
repository.addBuchung(konto.id, request)
|
||||
.onSuccess { aktualisiertesKonto ->
|
||||
_uiState.value = _uiState.value.copy(selectedKonto = aktualisiertesKonto)
|
||||
|
||||
Reference in New Issue
Block a user