(fix) RESTful API
This commit is contained in:
@@ -0,0 +1,14 @@
|
||||
package at.mocode.model
|
||||
|
||||
import at.mocode.shared.model.Artikel
|
||||
import com.benasher44.uuid.Uuid
|
||||
|
||||
interface ArtikelRepository {
|
||||
suspend fun findAll(): List<Artikel>
|
||||
suspend fun findById(id: Uuid): Artikel?
|
||||
suspend fun create(artikel: Artikel): Artikel
|
||||
suspend fun update(id: Uuid, artikel: Artikel): Artikel?
|
||||
suspend fun delete(id: Uuid): Boolean
|
||||
suspend fun findByVerbandsabgabe(istVerbandsabgabe: Boolean): List<Artikel>
|
||||
suspend fun search(query: String): List<Artikel>
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package at.mocode.model
|
||||
|
||||
import at.mocode.shared.stammdaten.Person
|
||||
import com.benasher44.uuid.Uuid
|
||||
|
||||
interface PersonRepository {
|
||||
suspend fun findAll(): List<Person>
|
||||
suspend fun findById(id: Uuid): Person?
|
||||
suspend fun findByOepsSatzNr(oepsSatzNr: String): Person?
|
||||
suspend fun create(person: Person): Person
|
||||
suspend fun update(id: Uuid, person: Person): Person?
|
||||
suspend fun delete(id: Uuid): Boolean
|
||||
suspend fun findByVereinId(vereinId: Uuid): List<Person>
|
||||
suspend fun search(query: String): List<Person>
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
package at.mocode.model
|
||||
|
||||
import at.mocode.shared.model.Artikel
|
||||
import at.mocode.tables.ArtikelTable
|
||||
import com.benasher44.uuid.Uuid
|
||||
import com.ionspin.kotlin.bignum.decimal.BigDecimal
|
||||
import kotlinx.datetime.Clock
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
class PostgresArtikelRepository : ArtikelRepository {
|
||||
|
||||
override suspend fun findAll(): List<Artikel> = transaction {
|
||||
ArtikelTable.selectAll().map { rowToArtikel(it) }
|
||||
}
|
||||
|
||||
override suspend fun findById(id: Uuid): Artikel? = transaction {
|
||||
ArtikelTable.select { ArtikelTable.id eq id }
|
||||
.map { rowToArtikel(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun create(artikel: Artikel): Artikel = transaction {
|
||||
val now = Clock.System.now()
|
||||
ArtikelTable.insert {
|
||||
it[id] = artikel.id
|
||||
it[bezeichnung] = artikel.bezeichnung
|
||||
it[preis] = artikel.preis.toStringExpanded()
|
||||
it[einheit] = artikel.einheit
|
||||
it[istVerbandsabgabe] = artikel.istVerbandsabgabe
|
||||
it[createdAt] = now
|
||||
it[updatedAt] = now
|
||||
}
|
||||
artikel.copy(createdAt = now, updatedAt = now)
|
||||
}
|
||||
|
||||
override suspend fun update(id: Uuid, artikel: Artikel): Artikel? = transaction {
|
||||
val updateCount = ArtikelTable.update({ ArtikelTable.id eq id }) {
|
||||
it[bezeichnung] = artikel.bezeichnung
|
||||
it[preis] = artikel.preis.toStringExpanded()
|
||||
it[einheit] = artikel.einheit
|
||||
it[istVerbandsabgabe] = artikel.istVerbandsabgabe
|
||||
it[updatedAt] = Clock.System.now()
|
||||
}
|
||||
if (updateCount > 0) {
|
||||
ArtikelTable.select { ArtikelTable.id eq id }
|
||||
.map { rowToArtikel(it) }
|
||||
.singleOrNull()
|
||||
} else null
|
||||
}
|
||||
|
||||
override suspend fun delete(id: Uuid): Boolean = transaction {
|
||||
ArtikelTable.deleteWhere { ArtikelTable.id eq id } > 0
|
||||
}
|
||||
|
||||
override suspend fun findByVerbandsabgabe(istVerbandsabgabe: Boolean): List<Artikel> = transaction {
|
||||
ArtikelTable.select { ArtikelTable.istVerbandsabgabe eq istVerbandsabgabe }
|
||||
.map { rowToArtikel(it) }
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<Artikel> = transaction {
|
||||
ArtikelTable.select {
|
||||
(ArtikelTable.bezeichnung.lowerCase() like "%${query.lowercase()}%") or
|
||||
(ArtikelTable.einheit.lowerCase() like "%${query.lowercase()}%")
|
||||
}.map { rowToArtikel(it) }
|
||||
}
|
||||
|
||||
private fun rowToArtikel(row: ResultRow): Artikel {
|
||||
return Artikel(
|
||||
id = row[ArtikelTable.id],
|
||||
bezeichnung = row[ArtikelTable.bezeichnung],
|
||||
preis = try {
|
||||
BigDecimal.parseString(row[ArtikelTable.preis])
|
||||
} catch (e: Exception) {
|
||||
BigDecimal.ZERO
|
||||
},
|
||||
einheit = row[ArtikelTable.einheit],
|
||||
istVerbandsabgabe = row[ArtikelTable.istVerbandsabgabe],
|
||||
createdAt = row[ArtikelTable.createdAt],
|
||||
updatedAt = row[ArtikelTable.updatedAt]
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,167 @@
|
||||
package at.mocode.model
|
||||
|
||||
import at.mocode.shared.enums.FunktionaerRolle
|
||||
import at.mocode.shared.stammdaten.LizenzInfo
|
||||
import at.mocode.shared.stammdaten.Person
|
||||
import at.mocode.tables.PersonenTable
|
||||
import com.benasher44.uuid.Uuid
|
||||
import com.benasher44.uuid.uuidFrom
|
||||
import kotlinx.datetime.Clock
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
class PostgresPersonRepository : PersonRepository {
|
||||
|
||||
override suspend fun findAll(): List<Person> = transaction {
|
||||
PersonenTable.selectAll().map { rowToPerson(it) }
|
||||
}
|
||||
|
||||
override suspend fun findById(id: Uuid): Person? = transaction {
|
||||
PersonenTable.select { PersonenTable.id eq id }
|
||||
.map { rowToPerson(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByOepsSatzNr(oepsSatzNr: String): Person? = transaction {
|
||||
PersonenTable.select { PersonenTable.oepsSatzNr eq oepsSatzNr }
|
||||
.map { rowToPerson(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun create(person: Person): Person = transaction {
|
||||
val now = Clock.System.now()
|
||||
PersonenTable.insert {
|
||||
it[id] = person.id
|
||||
it[oepsSatzNr] = person.oepsSatzNr
|
||||
it[nachname] = person.nachname
|
||||
it[vorname] = person.vorname
|
||||
it[titel] = person.titel
|
||||
it[geburtsdatum] = person.geburtsdatum
|
||||
it[geschlecht] = person.geschlechtE
|
||||
it[nationalitaet] = person.nationalitaet
|
||||
it[email] = person.email
|
||||
it[telefon] = person.telefon
|
||||
it[adresse] = person.adresse
|
||||
it[plz] = person.plz
|
||||
it[ort] = person.ort
|
||||
it[stammVereinId] = person.stammVereinId
|
||||
it[mitgliedsNummerIntern] = person.mitgliedsNummerIntern
|
||||
it[letzteZahlungJahr] = person.letzteZahlungJahr
|
||||
it[feiId] = person.feiId
|
||||
it[istGesperrt] = person.istGesperrt
|
||||
it[sperrGrund] = person.sperrGrund
|
||||
it[rollenCsv] = person.rollen.joinToString(",") { rolle -> rolle.name }
|
||||
it[qualifikationenRichterCsv] = person.qualifikationenRichter.joinToString(",")
|
||||
it[qualifikationenParcoursbauerCsv] = person.qualifikationenParcoursbauer.joinToString(",")
|
||||
it[istAktiv] = person.istAktiv
|
||||
it[createdAt] = now
|
||||
it[updatedAt] = now
|
||||
}
|
||||
person.copy(createdAt = now, updatedAt = now)
|
||||
}
|
||||
|
||||
override suspend fun update(id: Uuid, person: Person): Person? = transaction {
|
||||
val updateCount = PersonenTable.update({ PersonenTable.id eq id }) {
|
||||
it[nachname] = person.nachname
|
||||
it[vorname] = person.vorname
|
||||
it[titel] = person.titel
|
||||
it[geburtsdatum] = person.geburtsdatum
|
||||
it[geschlecht] = person.geschlechtE
|
||||
it[nationalitaet] = person.nationalitaet
|
||||
it[email] = person.email
|
||||
it[telefon] = person.telefon
|
||||
it[adresse] = person.adresse
|
||||
it[plz] = person.plz
|
||||
it[ort] = person.ort
|
||||
it[stammVereinId] = person.stammVereinId
|
||||
it[mitgliedsNummerIntern] = person.mitgliedsNummerIntern
|
||||
it[letzteZahlungJahr] = person.letzteZahlungJahr
|
||||
it[feiId] = person.feiId
|
||||
it[istGesperrt] = person.istGesperrt
|
||||
it[sperrGrund] = person.sperrGrund
|
||||
it[rollenCsv] = person.rollen.joinToString(",") { rolle -> rolle.name }
|
||||
it[qualifikationenRichterCsv] = person.qualifikationenRichter.joinToString(",")
|
||||
it[qualifikationenParcoursbauerCsv] = person.qualifikationenParcoursbauer.joinToString(",")
|
||||
it[istAktiv] = person.istAktiv
|
||||
it[updatedAt] = Clock.System.now()
|
||||
}
|
||||
if (updateCount > 0) {
|
||||
PersonenTable.select { PersonenTable.id eq id }
|
||||
.map { rowToPerson(it) }
|
||||
.singleOrNull()
|
||||
} else null
|
||||
}
|
||||
|
||||
override suspend fun delete(id: Uuid): Boolean = transaction {
|
||||
PersonenTable.deleteWhere { PersonenTable.id eq id } > 0
|
||||
}
|
||||
|
||||
override suspend fun findByVereinId(vereinId: Uuid): List<Person> = transaction {
|
||||
PersonenTable.select { PersonenTable.stammVereinId eq vereinId }
|
||||
.map { rowToPerson(it) }
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<Person> = transaction {
|
||||
PersonenTable.select {
|
||||
(PersonenTable.nachname.lowerCase() like "%${query.lowercase()}%") or
|
||||
(PersonenTable.vorname.lowerCase() like "%${query.lowercase()}%") or
|
||||
(PersonenTable.email?.lowerCase()?.like("%${query.lowercase()}%") ?: Op.FALSE)
|
||||
}.map { rowToPerson(it) }
|
||||
}
|
||||
|
||||
private fun rowToPerson(row: ResultRow): Person {
|
||||
return Person(
|
||||
id = row[PersonenTable.id],
|
||||
oepsSatzNr = row[PersonenTable.oepsSatzNr],
|
||||
nachname = row[PersonenTable.nachname],
|
||||
vorname = row[PersonenTable.vorname],
|
||||
titel = row[PersonenTable.titel],
|
||||
geburtsdatum = row[PersonenTable.geburtsdatum],
|
||||
geschlechtE = row[PersonenTable.geschlecht],
|
||||
nationalitaet = row[PersonenTable.nationalitaet],
|
||||
email = row[PersonenTable.email],
|
||||
telefon = row[PersonenTable.telefon],
|
||||
adresse = row[PersonenTable.adresse],
|
||||
plz = row[PersonenTable.plz],
|
||||
ort = row[PersonenTable.ort],
|
||||
stammVereinId = row[PersonenTable.stammVereinId],
|
||||
mitgliedsNummerIntern = row[PersonenTable.mitgliedsNummerIntern],
|
||||
letzteZahlungJahr = row[PersonenTable.letzteZahlungJahr],
|
||||
feiId = row[PersonenTable.feiId],
|
||||
istGesperrt = row[PersonenTable.istGesperrt],
|
||||
sperrGrund = row[PersonenTable.sperrGrund],
|
||||
rollen = parseRollen(row[PersonenTable.rollenCsv]),
|
||||
lizenzen = emptyList(), // TODO: Load from separate table if needed
|
||||
qualifikationenRichter = parseQualifikationen(row[PersonenTable.qualifikationenRichterCsv]),
|
||||
qualifikationenParcoursbauer = parseQualifikationen(row[PersonenTable.qualifikationenParcoursbauerCsv]),
|
||||
istAktiv = row[PersonenTable.istAktiv],
|
||||
createdAt = row[PersonenTable.createdAt],
|
||||
updatedAt = row[PersonenTable.updatedAt]
|
||||
)
|
||||
}
|
||||
|
||||
private fun parseRollen(rollenCsv: String?): Set<FunktionaerRolle> {
|
||||
return if (rollenCsv.isNullOrBlank()) {
|
||||
emptySet()
|
||||
} else {
|
||||
rollenCsv.split(",")
|
||||
.mapNotNull { roleName ->
|
||||
try {
|
||||
FunktionaerRolle.valueOf(roleName.trim())
|
||||
} catch (e: IllegalArgumentException) {
|
||||
null
|
||||
}
|
||||
}
|
||||
.toSet()
|
||||
}
|
||||
}
|
||||
|
||||
private fun parseQualifikationen(qualifikationenCsv: String?): List<String> {
|
||||
return if (qualifikationenCsv.isNullOrBlank()) {
|
||||
emptyList()
|
||||
} else {
|
||||
qualifikationenCsv.split(",").map { it.trim() }.filter { it.isNotEmpty() }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
package at.mocode.model
|
||||
|
||||
import at.mocode.shared.stammdaten.Verein
|
||||
import at.mocode.tables.VereineTable
|
||||
import com.benasher44.uuid.Uuid
|
||||
import kotlinx.datetime.Clock
|
||||
import org.jetbrains.exposed.sql.*
|
||||
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
|
||||
import org.jetbrains.exposed.sql.transactions.transaction
|
||||
|
||||
class PostgresVereinRepository : VereinRepository {
|
||||
|
||||
override suspend fun findAll(): List<Verein> = transaction {
|
||||
VereineTable.selectAll().map { rowToVerein(it) }
|
||||
}
|
||||
|
||||
override suspend fun findById(id: Uuid): Verein? = transaction {
|
||||
VereineTable.select { VereineTable.id eq id }
|
||||
.map { rowToVerein(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun findByOepsVereinsNr(oepsVereinsNr: String): Verein? = transaction {
|
||||
VereineTable.select { VereineTable.oepsVereinsNr eq oepsVereinsNr }
|
||||
.map { rowToVerein(it) }
|
||||
.singleOrNull()
|
||||
}
|
||||
|
||||
override suspend fun create(verein: Verein): Verein = transaction {
|
||||
val now = Clock.System.now()
|
||||
VereineTable.insert {
|
||||
it[id] = verein.id
|
||||
it[oepsVereinsNr] = verein.oepsVereinsNr
|
||||
it[name] = verein.name
|
||||
it[kuerzel] = verein.kuerzel
|
||||
it[bundesland] = verein.bundesland
|
||||
it[adresse] = verein.adresse
|
||||
it[plz] = verein.plz
|
||||
it[ort] = verein.ort
|
||||
it[email] = verein.email
|
||||
it[telefon] = verein.telefon
|
||||
it[webseite] = verein.webseite
|
||||
it[istAktiv] = verein.istAktiv
|
||||
it[createdAt] = now
|
||||
it[updatedAt] = now
|
||||
}
|
||||
verein.copy(createdAt = now, updatedAt = now)
|
||||
}
|
||||
|
||||
override suspend fun update(id: Uuid, verein: Verein): Verein? = transaction {
|
||||
val updateCount = VereineTable.update({ VereineTable.id eq id }) {
|
||||
it[name] = verein.name
|
||||
it[kuerzel] = verein.kuerzel
|
||||
it[bundesland] = verein.bundesland
|
||||
it[adresse] = verein.adresse
|
||||
it[plz] = verein.plz
|
||||
it[ort] = verein.ort
|
||||
it[email] = verein.email
|
||||
it[telefon] = verein.telefon
|
||||
it[webseite] = verein.webseite
|
||||
it[istAktiv] = verein.istAktiv
|
||||
it[updatedAt] = Clock.System.now()
|
||||
}
|
||||
if (updateCount > 0) {
|
||||
VereineTable.select { VereineTable.id eq id }
|
||||
.map { rowToVerein(it) }
|
||||
.singleOrNull()
|
||||
} else null
|
||||
}
|
||||
|
||||
override suspend fun delete(id: Uuid): Boolean = transaction {
|
||||
VereineTable.deleteWhere { VereineTable.id eq id } > 0
|
||||
}
|
||||
|
||||
override suspend fun findByBundesland(bundesland: String): List<Verein> = transaction {
|
||||
VereineTable.select { VereineTable.bundesland eq bundesland }
|
||||
.map { rowToVerein(it) }
|
||||
}
|
||||
|
||||
override suspend fun search(query: String): List<Verein> = transaction {
|
||||
VereineTable.select {
|
||||
(VereineTable.name.lowerCase() like "%${query.lowercase()}%") or
|
||||
(VereineTable.kuerzel?.lowerCase()?.like("%${query.lowercase()}%") ?: Op.FALSE) or
|
||||
(VereineTable.ort?.lowerCase()?.like("%${query.lowercase()}%") ?: Op.FALSE)
|
||||
}.map { rowToVerein(it) }
|
||||
}
|
||||
|
||||
private fun rowToVerein(row: ResultRow): Verein {
|
||||
return Verein(
|
||||
id = row[VereineTable.id],
|
||||
oepsVereinsNr = row[VereineTable.oepsVereinsNr],
|
||||
name = row[VereineTable.name],
|
||||
kuerzel = row[VereineTable.kuerzel],
|
||||
bundesland = row[VereineTable.bundesland],
|
||||
adresse = row[VereineTable.adresse],
|
||||
plz = row[VereineTable.plz],
|
||||
ort = row[VereineTable.ort],
|
||||
email = row[VereineTable.email],
|
||||
telefon = row[VereineTable.telefon],
|
||||
webseite = row[VereineTable.webseite],
|
||||
istAktiv = row[VereineTable.istAktiv],
|
||||
createdAt = row[VereineTable.createdAt],
|
||||
updatedAt = row[VereineTable.updatedAt]
|
||||
)
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package at.mocode.model
|
||||
|
||||
import at.mocode.shared.stammdaten.Verein
|
||||
import com.benasher44.uuid.Uuid
|
||||
|
||||
interface VereinRepository {
|
||||
suspend fun findAll(): List<Verein>
|
||||
suspend fun findById(id: Uuid): Verein?
|
||||
suspend fun findByOepsVereinsNr(oepsVereinsNr: String): Verein?
|
||||
suspend fun create(verein: Verein): Verein
|
||||
suspend fun update(id: Uuid, verein: Verein): Verein?
|
||||
suspend fun delete(id: Uuid): Boolean
|
||||
suspend fun findByBundesland(bundesland: String): List<Verein>
|
||||
suspend fun search(query: String): List<Verein>
|
||||
}
|
||||
@@ -0,0 +1,130 @@
|
||||
package at.mocode.routes
|
||||
|
||||
import at.mocode.model.ArtikelRepository
|
||||
import at.mocode.model.PostgresArtikelRepository
|
||||
import at.mocode.shared.model.Artikel
|
||||
import com.benasher44.uuid.uuidFrom
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
fun Route.artikelRoutes() {
|
||||
val artikelRepository: ArtikelRepository = PostgresArtikelRepository()
|
||||
|
||||
route("/api/artikel") {
|
||||
// GET /api/artikel - Get all articles
|
||||
get {
|
||||
try {
|
||||
val artikel = artikelRepository.findAll()
|
||||
call.respond(HttpStatusCode.OK, artikel)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/artikel/{id} - Get article by ID
|
||||
get("/{id}") {
|
||||
try {
|
||||
val id = call.parameters["id"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing artikel ID")
|
||||
)
|
||||
val uuid = uuidFrom(id)
|
||||
val artikel = artikelRepository.findById(uuid)
|
||||
if (artikel != null) {
|
||||
call.respond(HttpStatusCode.OK, artikel)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Artikel not found"))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/artikel/search?q={query} - Search articles
|
||||
get("/search") {
|
||||
try {
|
||||
val query = call.request.queryParameters["q"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing search query parameter 'q'")
|
||||
)
|
||||
val artikel = artikelRepository.search(query)
|
||||
call.respond(HttpStatusCode.OK, artikel)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/artikel/verbandsabgabe/{istVerbandsabgabe} - Get articles by association fee status
|
||||
get("/verbandsabgabe/{istVerbandsabgabe}") {
|
||||
try {
|
||||
val istVerbandsabgabe = call.parameters["istVerbandsabgabe"]?.toBoolean() ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing or invalid verbandsabgabe parameter")
|
||||
)
|
||||
val artikel = artikelRepository.findByVerbandsabgabe(istVerbandsabgabe)
|
||||
call.respond(HttpStatusCode.OK, artikel)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/artikel - Create new article
|
||||
post {
|
||||
try {
|
||||
val artikel = call.receive<Artikel>()
|
||||
val createdArtikel = artikelRepository.create(artikel)
|
||||
call.respond(HttpStatusCode.Created, createdArtikel)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// PUT /api/artikel/{id} - Update article
|
||||
put("/{id}") {
|
||||
try {
|
||||
val id = call.parameters["id"] ?: return@put call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing artikel ID")
|
||||
)
|
||||
val uuid = uuidFrom(id)
|
||||
val artikel = call.receive<Artikel>()
|
||||
val updatedArtikel = artikelRepository.update(uuid, artikel)
|
||||
if (updatedArtikel != null) {
|
||||
call.respond(HttpStatusCode.OK, updatedArtikel)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Artikel not found"))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE /api/artikel/{id} - Delete article
|
||||
delete("/{id}") {
|
||||
try {
|
||||
val id = call.parameters["id"] ?: return@delete call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing artikel ID")
|
||||
)
|
||||
val uuid = uuidFrom(id)
|
||||
val deleted = artikelRepository.delete(uuid)
|
||||
if (deleted) {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Artikel not found"))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
package at.mocode.routes
|
||||
|
||||
import at.mocode.model.PersonRepository
|
||||
import at.mocode.model.PostgresPersonRepository
|
||||
import at.mocode.shared.stammdaten.Person
|
||||
import com.benasher44.uuid.uuidFrom
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
fun Route.personRoutes() {
|
||||
val personRepository: PersonRepository = PostgresPersonRepository()
|
||||
|
||||
route("/api/persons") {
|
||||
// GET /api/persons - Get all persons
|
||||
get {
|
||||
try {
|
||||
val persons = personRepository.findAll()
|
||||
call.respond(HttpStatusCode.OK, persons)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/persons/{id} - Get person by ID
|
||||
get("/{id}") {
|
||||
try {
|
||||
val id = call.parameters["id"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing person ID")
|
||||
)
|
||||
val uuid = uuidFrom(id)
|
||||
val person = personRepository.findById(uuid)
|
||||
if (person != null) {
|
||||
call.respond(HttpStatusCode.OK, person)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Person not found"))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/persons/oeps/{oepsSatzNr} - Get person by OEPS number
|
||||
get("/oeps/{oepsSatzNr}") {
|
||||
try {
|
||||
val oepsSatzNr = call.parameters["oepsSatzNr"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing OEPS Satz number")
|
||||
)
|
||||
val person = personRepository.findByOepsSatzNr(oepsSatzNr)
|
||||
if (person != null) {
|
||||
call.respond(HttpStatusCode.OK, person)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Person not found"))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/persons/search?q={query} - Search persons
|
||||
get("/search") {
|
||||
try {
|
||||
val query = call.request.queryParameters["q"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing search query parameter 'q'")
|
||||
)
|
||||
val persons = personRepository.search(query)
|
||||
call.respond(HttpStatusCode.OK, persons)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/persons/verein/{vereinId} - Get persons by club ID
|
||||
get("/verein/{vereinId}") {
|
||||
try {
|
||||
val vereinId = call.parameters["vereinId"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing verein ID")
|
||||
)
|
||||
val uuid = uuidFrom(vereinId)
|
||||
val persons = personRepository.findByVereinId(uuid)
|
||||
call.respond(HttpStatusCode.OK, persons)
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/persons - Create new person
|
||||
post {
|
||||
try {
|
||||
val person = call.receive<Person>()
|
||||
val createdPerson = personRepository.create(person)
|
||||
call.respond(HttpStatusCode.Created, createdPerson)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// PUT /api/persons/{id} - Update person
|
||||
put("/{id}") {
|
||||
try {
|
||||
val id = call.parameters["id"] ?: return@put call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing person ID")
|
||||
)
|
||||
val uuid = uuidFrom(id)
|
||||
val person = call.receive<Person>()
|
||||
val updatedPerson = personRepository.update(uuid, person)
|
||||
if (updatedPerson != null) {
|
||||
call.respond(HttpStatusCode.OK, updatedPerson)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Person not found"))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE /api/persons/{id} - Delete person
|
||||
delete("/{id}") {
|
||||
try {
|
||||
val id = call.parameters["id"] ?: return@delete call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing person ID")
|
||||
)
|
||||
val uuid = uuidFrom(id)
|
||||
val deleted = personRepository.delete(uuid)
|
||||
if (deleted) {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Person not found"))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,148 @@
|
||||
package at.mocode.routes
|
||||
|
||||
import at.mocode.model.PostgresVereinRepository
|
||||
import at.mocode.model.VereinRepository
|
||||
import at.mocode.shared.stammdaten.Verein
|
||||
import com.benasher44.uuid.uuidFrom
|
||||
import io.ktor.http.*
|
||||
import io.ktor.server.application.*
|
||||
import io.ktor.server.request.*
|
||||
import io.ktor.server.response.*
|
||||
import io.ktor.server.routing.*
|
||||
|
||||
fun Route.vereinRoutes() {
|
||||
val vereinRepository: VereinRepository = PostgresVereinRepository()
|
||||
|
||||
route("/api/vereine") {
|
||||
// GET /api/vereine - Get all clubs
|
||||
get {
|
||||
try {
|
||||
val vereine = vereinRepository.findAll()
|
||||
call.respond(HttpStatusCode.OK, vereine)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/vereine/{id} - Get club by ID
|
||||
get("/{id}") {
|
||||
try {
|
||||
val id = call.parameters["id"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing verein ID")
|
||||
)
|
||||
val uuid = uuidFrom(id)
|
||||
val verein = vereinRepository.findById(uuid)
|
||||
if (verein != null) {
|
||||
call.respond(HttpStatusCode.OK, verein)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Verein not found"))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/vereine/oeps/{oepsVereinsNr} - Get club by OEPS number
|
||||
get("/oeps/{oepsVereinsNr}") {
|
||||
try {
|
||||
val oepsVereinsNr = call.parameters["oepsVereinsNr"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing OEPS Vereins number")
|
||||
)
|
||||
val verein = vereinRepository.findByOepsVereinsNr(oepsVereinsNr)
|
||||
if (verein != null) {
|
||||
call.respond(HttpStatusCode.OK, verein)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Verein not found"))
|
||||
}
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/vereine/search?q={query} - Search clubs
|
||||
get("/search") {
|
||||
try {
|
||||
val query = call.request.queryParameters["q"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing search query parameter 'q'")
|
||||
)
|
||||
val vereine = vereinRepository.search(query)
|
||||
call.respond(HttpStatusCode.OK, vereine)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// GET /api/vereine/bundesland/{bundesland} - Get clubs by state
|
||||
get("/bundesland/{bundesland}") {
|
||||
try {
|
||||
val bundesland = call.parameters["bundesland"] ?: return@get call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing bundesland")
|
||||
)
|
||||
val vereine = vereinRepository.findByBundesland(bundesland)
|
||||
call.respond(HttpStatusCode.OK, vereine)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// POST /api/vereine - Create new club
|
||||
post {
|
||||
try {
|
||||
val verein = call.receive<Verein>()
|
||||
val createdVerein = vereinRepository.create(verein)
|
||||
call.respond(HttpStatusCode.Created, createdVerein)
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// PUT /api/vereine/{id} - Update club
|
||||
put("/{id}") {
|
||||
try {
|
||||
val id = call.parameters["id"] ?: return@put call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing verein ID")
|
||||
)
|
||||
val uuid = uuidFrom(id)
|
||||
val verein = call.receive<Verein>()
|
||||
val updatedVerein = vereinRepository.update(uuid, verein)
|
||||
if (updatedVerein != null) {
|
||||
call.respond(HttpStatusCode.OK, updatedVerein)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Verein not found"))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
|
||||
// DELETE /api/vereine/{id} - Delete club
|
||||
delete("/{id}") {
|
||||
try {
|
||||
val id = call.parameters["id"] ?: return@delete call.respond(
|
||||
HttpStatusCode.BadRequest,
|
||||
mapOf("error" to "Missing verein ID")
|
||||
)
|
||||
val uuid = uuidFrom(id)
|
||||
val deleted = vereinRepository.delete(uuid)
|
||||
if (deleted) {
|
||||
call.respond(HttpStatusCode.NoContent)
|
||||
} else {
|
||||
call.respond(HttpStatusCode.NotFound, mapOf("error" to "Verein not found"))
|
||||
}
|
||||
} catch (e: IllegalArgumentException) {
|
||||
call.respond(HttpStatusCode.BadRequest, mapOf("error" to "Invalid UUID format"))
|
||||
} catch (e: Exception) {
|
||||
call.respond(HttpStatusCode.InternalServerError, mapOf("error" to e.message))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user