Add audit logging for Bewerb changes, implement ZNS B-Satz export, enhance Zeitplan tab with audit log display, export dialog, and clickable Bewerb items, and integrate FixedWidthLineBuilder utility.

This commit is contained in:
2026-04-11 21:23:33 +02:00
parent d224e2c521
commit 92aecf9abf
11 changed files with 402 additions and 62 deletions
@@ -1,6 +1,7 @@
package at.mocode.core.utils.parser
import kotlinx.datetime.LocalDate
import kotlinx.datetime.number
/**
* A simple utility to parse fixed-width strings based on 1-based start positions and lengths.
@@ -61,3 +62,34 @@ class FixedWidthLineReader(private val line: String) {
}
}
}
/**
* Utility to build fixed-width lines based on 1-based start positions and lengths.
*/
class FixedWidthLineBuilder(length: Int) {
private val buffer = CharArray(length) { ' ' }
fun setString(start1Based: Int, length: Int, value: String?) {
if (value == null) return
val start0Based = start1Based - 1
val v = value.take(length)
v.forEachIndexed { index, c ->
if (start0Based + index < buffer.size) {
buffer[start0Based + index] = c
}
}
}
fun setInt(start1Based: Int, length: Int, value: Int?) {
if (value == null) return
setString(start1Based, length, value.toString().padStart(length, '0'))
}
fun setLocalDate(start1Based: Int, value: LocalDate?) {
if (value == null) return
val str = "${value.year}${value.month.number.toString().padStart(2, '0')}${value.day.toString().padStart(2, '0')}"
setString(start1Based, 8, str)
}
override fun toString(): String = buffer.concatToString()
}
@@ -3,7 +3,7 @@ package at.mocode.core.utils.database
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import org.jetbrains.exposed.v1.core.Transaction
import org.jetbrains.exposed.v1.jdbc.transactions.experimental.newSuspendedTransaction
import org.jetbrains.exposed.v1.jdbc.transactions.suspendTransaction
/**
* Utility for database operations using Exposed.
@@ -15,7 +15,7 @@ object DatabaseFactory {
*/
suspend fun <T> dbQuery(block: suspend Transaction.() -> T): T =
withContext(Dispatchers.IO) {
newSuspendedTransaction {
suspendTransaction {
block()
}
}
@@ -1,5 +1,6 @@
package at.mocode.zns.parser
import at.mocode.core.utils.parser.FixedWidthLineBuilder
import at.mocode.core.utils.parser.FixedWidthLineReader
import kotlinx.datetime.LocalDate
@@ -70,4 +71,36 @@ object ZnsBewerbParser {
datum = datum
)
}
/**
* Erzeugt eine B-Satz Zeile für die n2-XXXXX.dat Datei.
* Verwendet eine Standardlänge von 80 Zeichen.
*/
fun build(bewerb: ZnsBewerb): String {
val builder = FixedWidthLineBuilder(80)
// Stelle 1: ID (Blank) - Standardmäßig Blank durch Buffer-Initialisierung
// Stelle 2-3: Bewerbnummer (2-stellig)
builder.setInt(2, 2, bewerb.bewerbNummer % 100)
// Stelle 4: Abteilung
builder.setInt(4, 1, bewerb.abteilung)
// Stelle 5-39: Bewerbname
builder.setString(5, 35, bewerb.name)
// Stelle 40-43: Klasse
builder.setString(40, 4, bewerb.klasse)
// Stelle 44-51: Kategorie
builder.setString(44, 8, bewerb.kategorie)
// Stelle 53-60: Datum (JJJJMMTT) - Achtung: FixedWidthLineReader nutzte 53,8 (1-basiert)
builder.setLocalDate(53, bewerb.datum)
// Stelle 61-63: Bewerbnummer (3-stellig)
builder.setInt(61, 3, bewerb.bewerbNummer)
return builder.toString()
}
}