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:
+1
@@ -13,6 +13,7 @@ import kotlin.uuid.Uuid
|
||||
interface TeilnehmerKontoRepository {
|
||||
fun findByVeranstaltungAndPerson(veranstaltungId: Uuid, personId: Uuid): TeilnehmerKonto?
|
||||
fun findById(kontoId: Uuid): TeilnehmerKonto?
|
||||
fun findByVeranstaltung(veranstaltungId: Uuid): List<TeilnehmerKonto>
|
||||
fun save(konto: TeilnehmerKonto): TeilnehmerKonto
|
||||
fun updateSaldo(kontoId: Uuid, saldoCent: Long): Long
|
||||
}
|
||||
|
||||
+23
-2
@@ -53,18 +53,39 @@ class TeilnehmerKontoService(
|
||||
return transaction {
|
||||
val konto = kontoRepository.findById(kontoId) ?: throw IllegalArgumentException("Konto nicht gefunden: $kontoId")
|
||||
|
||||
// Validierung: Bestimmte Typen sind immer "Soll" (negativ), andere "Haben" (positiv/Zahlung)
|
||||
val validierterBetrag = when (typ) {
|
||||
BuchungsTyp.NENNGELD,
|
||||
BuchungsTyp.NENNGEBUEHR,
|
||||
BuchungsTyp.NACHNENNGEBUEHR,
|
||||
BuchungsTyp.STARTGEBUEHR,
|
||||
BuchungsTyp.BOXENGEBUEHR -> if (betragCent > 0) -betragCent else betragCent
|
||||
|
||||
BuchungsTyp.ZAHLUNG_BAR,
|
||||
BuchungsTyp.ZAHLUNG_KARTE,
|
||||
BuchungsTyp.GUTSCHRIFT -> if (betragCent < 0) -betragCent else betragCent
|
||||
|
||||
BuchungsTyp.STORNIERUNG -> betragCent // Storno kann beides sein (Gegenbuchung)
|
||||
}
|
||||
|
||||
val buchung = Buchung(
|
||||
kontoId = kontoId,
|
||||
betragCent = betragCent,
|
||||
betragCent = validierterBetrag,
|
||||
typ = typ,
|
||||
verwendungszweck = zweck
|
||||
)
|
||||
|
||||
buchungRepository.save(buchung)
|
||||
val neuerSaldo = konto.saldoCent + betragCent
|
||||
val neuerSaldo = konto.saldoCent + validierterBetrag
|
||||
kontoRepository.updateSaldo(kontoId, neuerSaldo)
|
||||
|
||||
kontoRepository.findById(kontoId)!!
|
||||
}
|
||||
}
|
||||
|
||||
fun getKontenFuerVeranstaltung(veranstaltungId: Uuid): List<TeilnehmerKonto> {
|
||||
return transaction {
|
||||
kontoRepository.findByVeranstaltung(veranstaltungId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
@file:OptIn(ExperimentalUuidApi::class)
|
||||
|
||||
package at.mocode.billing.service.api
|
||||
|
||||
import at.mocode.billing.domain.model.Buchung
|
||||
import at.mocode.billing.domain.model.BuchungsTyp
|
||||
import at.mocode.billing.domain.model.TeilnehmerKonto
|
||||
import at.mocode.billing.service.TeilnehmerKontoService
|
||||
import org.springframework.web.bind.annotation.*
|
||||
import kotlin.uuid.ExperimentalUuidApi
|
||||
import kotlin.uuid.Uuid
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/api/v1/billing")
|
||||
class BillingController(
|
||||
private val kontoService: TeilnehmerKontoService
|
||||
) {
|
||||
|
||||
@GetMapping("/konten/{kontoId}")
|
||||
fun getKonto(@PathVariable kontoId: String): TeilnehmerKonto? {
|
||||
return kontoService.getKontoById(Uuid.parse(kontoId))
|
||||
}
|
||||
|
||||
@GetMapping("/veranstaltungen/{veranstaltungId}/personen/{personId}")
|
||||
fun getOrCreateKonto(
|
||||
@PathVariable veranstaltungId: String,
|
||||
@PathVariable personId: String,
|
||||
@RequestParam(required = false) personName: String?
|
||||
): TeilnehmerKonto {
|
||||
return kontoService.getOrCreateKonto(
|
||||
Uuid.parse(veranstaltungId),
|
||||
Uuid.parse(personId),
|
||||
personName ?: "Unbekannter Teilnehmer"
|
||||
)
|
||||
}
|
||||
|
||||
@GetMapping("/konten/{kontoId}/historie")
|
||||
fun getHistorie(@PathVariable kontoId: String): List<Buchung> {
|
||||
return kontoService.getBuchungsHistorie(Uuid.parse(kontoId))
|
||||
}
|
||||
|
||||
@GetMapping("/veranstaltungen/{veranstaltungId}/konten")
|
||||
fun getKonten(@PathVariable veranstaltungId: String): List<TeilnehmerKonto> {
|
||||
return kontoService.getKontenFuerVeranstaltung(Uuid.parse(veranstaltungId))
|
||||
}
|
||||
|
||||
@PostMapping("/konten/{kontoId}/buche")
|
||||
fun buche(
|
||||
@PathVariable kontoId: String,
|
||||
@RequestBody request: BuchungRequest
|
||||
): TeilnehmerKonto {
|
||||
return kontoService.buche(
|
||||
Uuid.parse(kontoId),
|
||||
request.betragCent,
|
||||
request.typ,
|
||||
request.verwendungszweck
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
data class BuchungRequest(
|
||||
val betragCent: Long,
|
||||
val typ: BuchungsTyp,
|
||||
val verwendungszweck: String
|
||||
)
|
||||
+7
@@ -37,6 +37,13 @@ class ExposedTeilnehmerKontoRepository : TeilnehmerKontoRepository {
|
||||
?.toModel()
|
||||
}
|
||||
|
||||
override fun findByVeranstaltung(veranstaltungId: Uuid): List<TeilnehmerKonto> {
|
||||
return TeilnehmerKontoTable
|
||||
.selectAll()
|
||||
.where { TeilnehmerKontoTable.veranstaltungId eq veranstaltungId }
|
||||
.map { it.toModel() }
|
||||
}
|
||||
|
||||
override fun save(konto: TeilnehmerKonto): TeilnehmerKonto {
|
||||
val existing = findById(konto.kontoId)
|
||||
if (existing == null) {
|
||||
|
||||
Reference in New Issue
Block a user