meldestelle/events/README-EVENTS.md
2025-07-30 00:01:22 +02:00

458 lines
12 KiB
Markdown

# Events Module
## Überblick
Das Events-Modul ist eine umfassende Lösung zur Verwaltung von Pferdesportveranstaltungen. Es implementiert eine saubere Architektur mit Domain-Driven Design und bietet vollständige CRUD-Operationen sowie erweiterte Geschäftslogik für die Veranstaltungsplanung und -verwaltung.
## Funktionalität
### Verwaltete Entität
#### Veranstaltung (Event)
- **Grundinformationen**: Name, Beschreibung
- **Terminverwaltung**: Startdatum, Enddatum, Anmeldeschluss
- **Ort und Organisation**: Veranstaltungsort, Veranstalter-Verein-ID
- **Veranstaltungsdetails**: Sparten, Aktivitätsstatus, Öffentlichkeit, maximale Teilnehmerzahl
- **Audit-Felder**: Erstellungs- und Aktualisierungszeitstempel
- **Geschäftslogik**: Validierung, Anmeldestatus, Dauernberechnung
### Geschäftsoperationen
Das Modul bietet 10+ spezialisierte Repository-Operationen:
#### Basis-CRUD-Operationen
- `findById(id)` - Veranstaltung nach UUID suchen
- `save(veranstaltung)` - Veranstaltung speichern (erstellen/aktualisieren)
- `delete(id)` - Veranstaltung löschen
#### Such-Operationen
- `findByName(searchTerm, limit)` - Nach Namen suchen (Teilübereinstimmung)
- `findByVeranstalterVereinId(vereinId, activeOnly)` - Veranstaltungen eines Vereins
- `findAllActive(limit, offset)` - Alle aktiven Veranstaltungen
- `findPublicEvents(activeOnly)` - Öffentliche Veranstaltungen
#### Datumsbasierte Abfragen
- `findByDateRange(startDate, endDate, activeOnly)` - Veranstaltungen in Datumsbereich
- `findByStartDate(date, activeOnly)` - Veranstaltungen nach Startdatum
#### Zähl-Operationen
- `countActive()` - Anzahl aktiver Veranstaltungen
- `countByVeranstalterVereinId(vereinId, activeOnly)` - Anzahl Veranstaltungen pro Verein
## Architektur
Das Modul folgt der Clean Architecture mit klarer Trennung der Verantwortlichkeiten:
```
events/
├── events-domain/ # Domain Layer
│ ├── model/ # Domain Models
│ │ └── Veranstaltung.kt # Veranstaltungs-Entität mit Geschäftslogik
│ ├── repository/ # Repository Interfaces
│ │ └── VeranstaltungRepository.kt # 10+ Geschäftsoperationen
│ └── EventManagement.kt # Domain Service/Facade
├── events-application/ # Application Layer
│ └── usecase/ # Use Cases
│ ├── CreateVeranstaltungUseCase.kt
│ ├── GetVeranstaltungUseCase.kt
│ ├── UpdateVeranstaltungUseCase.kt
│ └── DeleteVeranstaltungUseCase.kt
├── events-infrastructure/ # Infrastructure Layer
│ └── persistence/ # Database Implementation
│ ├── VeranstaltungRepositoryImpl.kt
│ └── VeranstaltungTable.kt
├── events-api/ # API Layer
│ └── rest/ # REST Controllers
│ └── VeranstaltungController.kt
└── events-service/ # Service Layer
└── EventsServiceApplication.kt
```
### Domain Layer
- **1 Domain Model** mit reichhaltiger Geschäftslogik
- **1 Repository Interface** mit 10+ Geschäftsoperationen
- **Domain Service** für komplexe Veranstaltungslogik
- **Keine Abhängigkeiten** zu anderen Layern
### Application Layer
- **Use Cases** für CRUD-Operationen
- **Orchestrierung** von Domain-Services
- **Anwendungslogik** ohne UI-Abhängigkeiten
### Infrastructure Layer
- **Datenbankzugriff** mit Exposed ORM
- **Repository-Implementierung** mit PostgreSQL
- **Datenbankschema** und Migrationen
### API Layer
- **REST-Controller** für HTTP-Endpunkte
- **DTO-Mapping** zwischen Domain und API
- **Validierung** und Fehlerbehandlung
### Service Layer
- **Spring Boot Anwendung**
- **Dependency Injection** Konfiguration
- **Service-Konfiguration**
## Domain Model Details
### Veranstaltung-Entität
```kotlin
data class Veranstaltung(
val veranstaltungId: Uuid,
// Grundinformationen
var name: String,
var beschreibung: String? = null,
// Termine
var startDatum: LocalDate,
var endDatum: LocalDate,
// Ort und Organisation
var ort: String,
var veranstalterVereinId: Uuid,
// Veranstaltungsdetails
var sparten: List<SparteE> = emptyList(),
var istAktiv: Boolean = true,
var istOeffentlich: Boolean = true,
var maxTeilnehmer: Int? = null,
var anmeldeschluss: LocalDate? = null,
// Audit-Felder
val createdAt: Instant,
var updatedAt: Instant
)
```
### Geschäftslogik-Methoden
- `isRegistrationOpen()` - Prüfung ob Anmeldung noch möglich ist
- `getDurationInDays()` - Berechnung der Veranstaltungsdauer in Tagen
- `isMultiDay()` - Prüfung ob mehrtägige Veranstaltung
- `validate()` - Datenvalidierung mit Fehlerliste
- `withUpdatedTimestamp()` - Kopie mit aktualisiertem Zeitstempel
### Enumerationen
#### SparteE (Sportsparten)
- `DRESSUR` - Dressurreiten
- `SPRINGEN` - Springreiten
- `VIELSEITIGKEIT` - Vielseitigkeitsreiten
- `FAHREN` - Fahrsport
- `VOLTIGIEREN` - Voltigieren
- `WESTERN` - Westernreiten
- `DISTANZ` - Distanzreiten
## Repository-Operationen
### Erweiterte Such-Features
```kotlin
// Veranstaltungen nach Namen suchen
val events = veranstaltungRepository.findByName("Turnier", limit = 10)
// Veranstaltungen eines Vereins finden
val clubEvents = veranstaltungRepository.findByVeranstalterVereinId(
vereinId = clubId,
activeOnly = true
)
// Veranstaltungen in Datumsbereich suchen
val summerEvents = veranstaltungRepository.findByDateRange(
startDate = LocalDate(2024, 6, 1),
endDate = LocalDate(2024, 8, 31),
activeOnly = true
)
// Öffentliche Veranstaltungen finden
val publicEvents = veranstaltungRepository.findPublicEvents(activeOnly = true)
```
### Datumsbasierte Abfragen
```kotlin
// Veranstaltungen an einem bestimmten Tag
val todayEvents = veranstaltungRepository.findByStartDate(
date = LocalDate.now(),
activeOnly = true
)
// Alle aktiven Veranstaltungen
val activeEvents = veranstaltungRepository.findAllActive(limit = 100)
```
### Statistiken und Zählungen
```kotlin
// Anzahl aktiver Veranstaltungen
val totalActive = veranstaltungRepository.countActive()
// Anzahl Veranstaltungen pro Verein
val clubEventCount = veranstaltungRepository.countByVeranstalterVereinId(
vereinId = clubId,
activeOnly = true
)
```
## Use Cases
### CreateVeranstaltungUseCase
Erstellt eine neue Veranstaltung mit Validierung und Geschäftsregeln.
```kotlin
class CreateVeranstaltungUseCase(
private val veranstaltungRepository: VeranstaltungRepository
) {
suspend fun execute(veranstaltung: Veranstaltung): Veranstaltung {
// Validierung
val errors = veranstaltung.validate()
if (errors.isNotEmpty()) {
throw ValidationException(errors)
}
// Geschäftsregeln prüfen
if (veranstaltung.anmeldeschluss != null &&
veranstaltung.anmeldeschluss!! > veranstaltung.startDatum) {
throw BusinessRuleException("Anmeldeschluss muss vor Veranstaltungsbeginn liegen")
}
return veranstaltungRepository.save(veranstaltung)
}
}
```
### GetVeranstaltungUseCase
Ruft Veranstaltungsinformationen ab mit verschiedenen Suchkriterien.
### UpdateVeranstaltungUseCase
Aktualisiert Veranstaltungsinformationen mit Validierung.
### DeleteVeranstaltungUseCase
Löscht eine Veranstaltung (soft delete durch Deaktivierung).
## API-Endpunkte
Das Events-Modul stellt REST-Endpunkte über den VeranstaltungController bereit:
- `GET /api/events` - Alle aktiven Veranstaltungen abrufen
- `GET /api/events/{id}` - Veranstaltung nach ID abrufen
- `GET /api/events/search?name={name}` - Veranstaltungen nach Namen suchen
- `GET /api/events/club/{clubId}` - Veranstaltungen eines Vereins
- `GET /api/events/public` - Öffentliche Veranstaltungen
- `GET /api/events/date-range?start={start}&end={end}` - Veranstaltungen in Datumsbereich
- `GET /api/events/date/{date}` - Veranstaltungen an einem bestimmten Tag
- `POST /api/events` - Neue Veranstaltung erstellen
- `PUT /api/events/{id}` - Veranstaltung aktualisieren
- `DELETE /api/events/{id}` - Veranstaltung löschen
## Konfiguration
### Datenbankschema
Das Modul verwendet eine `events`-Tabelle mit folgenden Spalten:
- `veranstaltung_id` (UUID, Primary Key)
- `name` (Required)
- `beschreibung` (Text, Optional)
- `start_datum`, `end_datum` (Date, Required)
- `ort` (Required)
- `veranstalter_verein_id` (UUID, Foreign Key)
- `sparten` (JSON Array)
- `ist_aktiv`, `ist_oeffentlich` (Boolean)
- `max_teilnehmer` (Integer, Optional)
- `anmeldeschluss` (Date, Optional)
- `created_at`, `updated_at` (Timestamps)
### Service-Konfiguration
```yaml
# application.yml
events:
service:
name: events-service
port: 8084
database:
url: jdbc:postgresql://localhost:5432/meldestelle
table: events
business-rules:
max-duration-days: 30
min-registration-period-days: 7
allow-past-events: false
```
## Tests
### Integration Tests
Das Modul enthält umfassende Integrationstests:
```kotlin
@Test
fun `should create event with valid data`() {
// Test für Veranstaltungserstellung
}
@Test
fun `should find events by date range`() {
// Test für datumsbasierte Suche
}
@Test
fun `should validate registration deadline`() {
// Test für Anmeldeschluss-Validierung
}
@Test
fun `should find public events only`() {
// Test für öffentliche Veranstaltungen
}
```
### Test-Datenbank
Verwendet H2 In-Memory-Datenbank für Tests mit automatischem Schema-Setup.
## Deployment
### Docker
```dockerfile
FROM openjdk:21-jre-slim
COPY events-service.jar app.jar
EXPOSE 8084
ENTRYPOINT ["java", "-jar", "/app.jar"]
```
### Kubernetes
```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: events-service
spec:
replicas: 2
selector:
matchLabels:
app: events-service
template:
spec:
containers:
- name: events-service
image: meldestelle/events-service:latest
ports:
- containerPort: 8084
```
## Monitoring
### Metriken
- Anzahl aktiver Veranstaltungen
- Anzahl öffentlicher Veranstaltungen
- Durchschnittliche Veranstaltungsdauer
- API-Response-Zeiten
- Datenbankverbindungs-Pool
- Validierungsfehler-Rate
### Health Checks
- Datenbankverbindung
- Service-Verfügbarkeit
- Speicherverbrauch
- Externe System-Verbindungen
## Entwicklung
### Lokale Entwicklung
```bash
# Service starten
./gradlew :events:events-service:bootRun
# Tests ausführen
./gradlew :events:test
# Integration Tests
./gradlew :events:events-service:test
```
### Code-Qualität
- **Kotlin Coding Standards**
- **100% Test Coverage** für Domain Layer
- **Integration Tests** für alle Use Cases
- **API-Dokumentation** mit OpenAPI
## Geschäftsregeln
### Veranstaltungsplanung
1. **Datumsvalidierung**: Enddatum muss nach oder gleich Startdatum sein
2. **Anmeldeschluss**: Muss vor Veranstaltungsbeginn liegen
3. **Teilnehmerbegrenzung**: Maximale Teilnehmerzahl muss positiv sein
4. **Öffentlichkeit**: Private Veranstaltungen nur für Vereinsmitglieder
### Sparten-Management
- Unterstützung für alle österreichischen Pferdesport-Sparten
- Mehrfachauswahl möglich für kombinierte Veranstaltungen
- Sparten-spezifische Validierungsregeln
### Vereins-Integration
- Verknüpfung mit Vereinsverwaltung
- Berechtigung zur Veranstaltungserstellung
- Vereins-spezifische Konfigurationen
## Integration
### Externe Systeme
#### OEPS-Integration
- Synchronisation mit OEPS-Veranstaltungskalender
- Automatische Meldung bei OEPS-relevanten Veranstaltungen
- Import von OEPS-Veranstaltungsdaten
#### FEI-Integration
- Unterstützung für internationale Veranstaltungen
- FEI-Regularien und -Standards
- Automatische Klassifizierung
### Interne Module
#### Members-Modul
- Teilnehmerverwaltung
- Anmeldestatus-Tracking
- Mitgliedschaftsvalidierung
#### Horses-Modul
- Pferdeanmeldungen
- Eignung für Sparten
- Registrierungsstatus
## Zukünftige Erweiterungen
1. **Anmeldungssystem** - Vollständiges Teilnehmeranmeldungssystem
2. **Zeitplanung** - Detaillierte Zeitpläne und Startlisten
3. **Ergebniserfassung** - Integration mit Bewertungssystemen
4. **Livestreaming** - Integration mit Streaming-Plattformen
5. **Mobile App** - Mobile Anwendung für Teilnehmer
6. **Zahlungsintegration** - Startgebühren und Zahlungsabwicklung
7. **Wetterintegration** - Wettervorhersage und -warnungen
8. **Kapazitätsmanagement** - Stallplätze und Parkplätze
9. **Catering-Management** - Verpflegung und Bewirtung
10. **Sponsoring** - Sponsoren-Management und -präsentation
---
**Letzte Aktualisierung**: 25. Juli 2025
Für weitere Informationen zur Gesamtarchitektur siehe [README.md](../README.md).