Extend Bewerb domain model: add new properties (e.g., Beschreibung, Aufgabe, BeginnZeitTyp), update Enums, and align repository structures.

This commit is contained in:
Stefan Mogeritsch 2026-04-08 22:58:53 +02:00
parent d91d88855e
commit 085656a85b
3 changed files with 87 additions and 4 deletions

View File

@ -3,11 +3,14 @@
package at.mocode.entries.domain.model package at.mocode.entries.domain.model
import at.mocode.core.domain.model.AbteilungsTeilungsTypE import at.mocode.core.domain.model.AbteilungsTeilungsTypE
import at.mocode.core.domain.model.BeginnZeitTypE
import at.mocode.core.domain.model.PruefungsTypE import at.mocode.core.domain.model.PruefungsTypE
import at.mocode.core.domain.model.SparteE import at.mocode.core.domain.model.SparteE
import at.mocode.core.domain.model.TurnierkategorieE import at.mocode.core.domain.model.TurnierkategorieE
import at.mocode.core.domain.serialization.InstantSerializer import at.mocode.core.domain.serialization.InstantSerializer
import at.mocode.core.domain.serialization.UuidSerializer import at.mocode.core.domain.serialization.UuidSerializer
import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalTime
import kotlinx.serialization.Serializable import kotlinx.serialization.Serializable
import kotlin.time.Clock import kotlin.time.Clock
import kotlin.time.Instant import kotlin.time.Instant
@ -17,7 +20,7 @@ import kotlin.uuid.Uuid
* Domain-Modell für einen Bewerb im registration-context. * Domain-Modell für einen Bewerb im registration-context.
* *
* Ein Bewerb ist eine einzelne Prüfung innerhalb eines Turniers (z.B. Stilspringen 90 cm"). * Ein Bewerb ist eine einzelne Prüfung innerhalb eines Turniers (z.B. Stilspringen 90 cm").
* Er kann in mehrere [DomAbteilung]en aufgeteilt sein. Die Abteilungs-Warn-Logik basiert * Er kann in mehrere [Abteilung]en aufgeteilt sein. Die Abteilungs-Warn-Logik basiert
* auf den ÖTO-Schwellenwerten (§ 39 A-Teil + spartenspezifische Bestimmungen). * auf den ÖTO-Schwellenwerten (§ 39 A-Teil + spartenspezifische Bestimmungen).
* *
* Aggregate Root des `registration-context` für den Bewerbs-Workflow. * Aggregate Root des `registration-context` für den Bewerbs-Workflow.
@ -34,12 +37,27 @@ import kotlin.uuid.Uuid
* @property maxStarterProAbteilung Maximale Starter pro Abteilung (0 = kein Limit gesetzt). * @property maxStarterProAbteilung Maximale Starter pro Abteilung (0 = kein Limit gesetzt).
* @property istMeisterschaft Ob es sich um einen Meisterschaftsbewerb handelt (Ausnahme von § 39 Abs. 4). * @property istMeisterschaft Ob es sich um einen Meisterschaftsbewerb handelt (Ausnahme von § 39 Abs. 4).
* @property istNachnennungErlaubt Ob Nachnennungen für diesen Bewerb zugelassen sind. * @property istNachnennungErlaubt Ob Nachnennungen für diesen Bewerb zugelassen sind.
* @property beschreibung Optionale Beschreibung (z.B. "Pony Einsteiger Cup").
* @property aufgabe Aufgaben-Bezeichnung gemäß ÖTO (z.B. "R1", "L1").
* @property aufgabenNummer Aufgaben-Nummer (z.B. "R1/2024").
* @property paraGrade Para-Equestrian Grade (z.B. "Grade I"), falls zutreffend.
* @property austragungsplatzId Referenz auf den Austragungsplatz (UUID aus events-context).
* @property richterEinsaetze Liste der Richter-Einsätze für diesen Bewerb.
* @property geplantesDatum Geplantes Datum des Bewerbs.
* @property beginnZeitTyp Typ des Beginnzeit-Eintrags (FIX oder ANSCHLIESSEND).
* @property beginnZeit Geplante Beginnzeit (nur bei FIX).
* @property reitdauerMinuten Geplante Reitdauer in Minuten.
* @property umbauMinuten Geplante Umbauzeit in Minuten.
* @property besichtigungMinuten Geplante Besichtigungszeit in Minuten.
* @property stechenGeplant Ob ein Stechen geplant ist.
* @property startgeldCent Startgeld in Cent (z.B. 1500 = 15,00 ).
* @property geldpreisAusbezahlt Ob der Geldpreis bereits ausbezahlt wurde.
* @property bemerkungen Interne Notizen. * @property bemerkungen Interne Notizen.
* @property createdAt Erstellungszeitpunkt. * @property createdAt Erstellungszeitpunkt.
* @property updatedAt Letzter Änderungszeitpunkt. * @property updatedAt Letzter Änderungszeitpunkt.
*/ */
@Serializable @Serializable
data class DomBewerb( data class Bewerb(
@Serializable(with = UuidSerializer::class) @Serializable(with = UuidSerializer::class)
val bewerbId: Uuid = Uuid.random(), val bewerbId: Uuid = Uuid.random(),
@ -61,6 +79,30 @@ data class DomBewerb(
var teilungsTyp: AbteilungsTeilungsTypE = AbteilungsTeilungsTypE.KEINE, var teilungsTyp: AbteilungsTeilungsTypE = AbteilungsTeilungsTypE.KEINE,
var maxStarterProAbteilung: Int = 0, var maxStarterProAbteilung: Int = 0,
// Text & Details
var beschreibung: String? = null,
var aufgabe: String? = null,
var aufgabenNummer: String? = null,
var paraGrade: String? = null,
// Ort & Funktionäre
@Serializable(with = UuidSerializer::class)
var austragungsplatzId: Uuid? = null,
var richterEinsaetze: List<RichterEinsatz> = emptyList(),
// Zeitplan
var geplantesDatum: LocalDate? = null,
var beginnZeitTyp: BeginnZeitTypE? = null,
var beginnZeit: LocalTime? = null,
var reitdauerMinuten: Int? = null,
var umbauMinuten: Int? = null,
var besichtigungMinuten: Int? = null,
var stechenGeplant: Boolean = false,
// Finanzen
var startgeldCent: Long? = null,
var geldpreisAusbezahlt: Boolean = false,
// Flags // Flags
var istMeisterschaft: Boolean = false, var istMeisterschaft: Boolean = false,
var istNachnennungErlaubt: Boolean = true, var istNachnennungErlaubt: Boolean = true,
@ -146,5 +188,5 @@ data class DomBewerb(
/** /**
* Erstellt eine Kopie mit aktualisiertem Zeitstempel. * Erstellt eine Kopie mit aktualisiertem Zeitstempel.
*/ */
fun withUpdatedTimestamp(): DomBewerb = this.copy(updatedAt = Clock.System.now()) fun withUpdatedTimestamp(): Bewerb = this.copy(updatedAt = Clock.System.now())
} }

View File

@ -2,6 +2,11 @@
package at.mocode.entries.service.bewerbe package at.mocode.entries.service.bewerbe
import at.mocode.core.domain.model.AbteilungsTeilungsTypE
import at.mocode.core.domain.model.BeginnZeitTypE
import at.mocode.entries.domain.model.RichterEinsatz
import kotlinx.datetime.LocalDate
import kotlinx.datetime.LocalTime
import kotlin.uuid.Uuid import kotlin.uuid.Uuid
data class Bewerb( data class Bewerb(
@ -10,6 +15,27 @@ data class Bewerb(
val klasse: String, val klasse: String,
val hoeheCm: Int?, val hoeheCm: Int?,
val bezeichnung: String, val bezeichnung: String,
// Abteilungs-Konfiguration
val teilungsTyp: AbteilungsTeilungsTypE? = null,
// Text & Details
val beschreibung: String? = null,
val aufgabe: String? = null,
val aufgabenNummer: String? = null,
val paraGrade: String? = null,
// Ort & Funktionäre
val austragungsplatzId: Uuid? = null,
val richterEinsaetze: List<RichterEinsatz> = emptyList(),
// Zeitplan
val geplantesDatum: LocalDate? = null,
val beginnZeitTyp: BeginnZeitTypE? = null,
val beginnZeit: LocalTime? = null,
val reitdauerMinuten: Int? = null,
val umbauMinuten: Int? = null,
val besichtigungMinuten: Int? = null,
val stechenGeplant: Boolean = false,
// Finanzen
val startgeldCent: Long? = null,
val geldpreisAusbezahlt: Boolean = false,
) )
interface BewerbRepository { interface BewerbRepository {

View File

@ -372,7 +372,22 @@ enum class AbteilungsTeilungsTypE {
ORGANISATORISCH, ORGANISATORISCH,
/** Separate Siegerehrung: Abteilungen werden nicht zusammengeführt, jede Abt. hat eigene Platzierung */ /** Separate Siegerehrung: Abteilungen werden nicht zusammengeführt, jede Abt. hat eigene Platzierung */
SEPARATE_SIEGEREHRUNG SEPARATE_SIEGEREHRUNG,
/** Manuelle Teilung: Abteilungen werden vom Benutzer manuell festgelegt */
MANUELL
}
/**
* Typ des Beginnzeit-Eintrags für einen Bewerb im Zeitplan.
*/
@Serializable
enum class BeginnZeitTypE {
/** Fixer Startzeitpunkt (z.B. 09:00 Uhr) */
FIX,
/** Anschließend an den vorherigen Bewerb */
ANSCHLIESSEND
} }
/** /**