# Horses Module

## Überblick

Das Horses-Modul ist eine umfassende Lösung zur Verwaltung von Pferden für Pferdesportorganisationen. Es implementiert eine saubere Architektur mit Domain-Driven Design und bietet vollständige CRUD-Operationen sowie erweiterte Geschäftslogik für die Pferderegistrierung und -verwaltung.

## Funktionalität

### Verwaltete Entität

#### Pferd (DomPferd)
- **Grundinformationen**: Name, Geschlecht, Geburtsdatum, Rasse, Farbe
- **Besitz und Verantwortung**: Besitzer-ID, verantwortliche Person
- **Zuchtinformationen**: Züchtername, Zuchtbuchnummer
- **Identifikationsnummern**: Lebensnummer, Chipnummer, Passnummer, OEPS-Nummer, FEI-Nummer
- **Abstammung**: Vater, Mutter, Muttervater
- **Körperliche Merkmale**: Stockmaß (Höhe in cm)
- **Status und Verwaltung**: Aktivitätsstatus, Bemerkungen, Datenquelle
- **Audit-Felder**: Erstellungs- und Aktualisierungszeitstempel

### Geschäftsoperationen

Das Modul bietet 25+ spezialisierte Repository-Operationen:

#### Basis-CRUD-Operationen
- `findById(id)` - Pferd nach UUID suchen
- `save(horse)` - Pferd speichern (erstellen/aktualisieren)
- `delete(id)` - Pferd löschen

#### Such-Operationen nach Identifikationsnummern
- `findByLebensnummer(lebensnummer)` - Nach Lebensnummer suchen
- `findByChipNummer(chipNummer)` - Nach Chipnummer suchen
- `findByPassNummer(passNummer)` - Nach Passnummer suchen
- `findByOepsNummer(oepsNummer)` - Nach OEPS-Nummer suchen
- `findByFeiNummer(feiNummer)` - Nach FEI-Nummer suchen

#### Such-Operationen nach Eigenschaften
- `findByName(searchTerm, limit)` - Nach Namen suchen (Teilübereinstimmung)
- `findByOwnerId(ownerId, activeOnly)` - Pferde eines Besitzers
- `findByResponsiblePersonId(personId, activeOnly)` - Pferde einer verantwortlichen Person
- `findByGeschlecht(geschlecht, activeOnly, limit)` - Nach Geschlecht filtern
- `findByRasse(rasse, activeOnly, limit)` - Nach Rasse filtern

#### Datumsbasierte Abfragen
- `findByBirthYear(birthYear, activeOnly)` - Pferde nach Geburtsjahr
- `findByBirthYearRange(fromYear, toYear, activeOnly)` - Pferde nach Geburtsjahr-Bereich

#### Registrierungs-Abfragen
- `findAllActive(limit)` - Alle aktiven Pferde
- `findOepsRegistered(activeOnly)` - OEPS-registrierte Pferde
- `findFeiRegistered(activeOnly)` - FEI-registrierte Pferde

#### Validierungs-Operationen
- `existsByLebensnummer(lebensnummer)` - Prüfung auf doppelte Lebensnummer
- `existsByChipNummer(chipNummer)` - Prüfung auf doppelte Chipnummer
- `existsByPassNummer(passNummer)` - Prüfung auf doppelte Passnummer
- `existsByOepsNummer(oepsNummer)` - Prüfung auf doppelte OEPS-Nummer
- `existsByFeiNummer(feiNummer)` - Prüfung auf doppelte FEI-Nummer

#### Zähl-Operationen
- `countActive()` - Anzahl aktiver Pferde
- `countByOwnerId(ownerId, activeOnly)` - Anzahl Pferde pro Besitzer
- `countOepsRegistered(activeOnly)` - Anzahl OEPS-registrierter Pferde ✨ **NEU**
- `countFeiRegistered(activeOnly)` - Anzahl FEI-registrierter Pferde ✨ **NEU**

## Architektur

Das Modul folgt der Clean Architecture mit klarer Trennung der Verantwortlichkeiten:

```
horses/
├── horses-domain/               # Domain Layer
│   ├── model/                   # Domain Models
│   │   └── DomPferd.kt         # Pferd-Entität mit Geschäftslogik
│   └── repository/             # Repository Interfaces
│       └── HorseRepository.kt  # 25+ Geschäftsoperationen
├── horses-application/          # Application Layer
│   └── usecase/                # Use Cases
│       ├── CreateHorseUseCase.kt
│       ├── GetHorseUseCase.kt
│       ├── UpdateHorseUseCase.kt
│       └── DeleteHorseUseCase.kt
├── horses-infrastructure/       # Infrastructure Layer
│   └── persistence/            # Database Implementation
│       ├── HorseRepositoryImpl.kt
│       └── HorseTable.kt
├── horses-api/                 # API Layer
│   └── rest/                   # REST Controllers
│       └── HorseController.kt
└── horses-service/             # Service Layer
    ├── HorsesServiceApplication.kt
    └── test/                   # Integration Tests
        └── HorseServiceIntegrationTest.kt
```

### Domain Layer
- **1 Domain Model** mit reichhaltiger Geschäftslogik
- **1 Repository Interface** mit 25+ Geschäftsoperationen
- **Geschäftsregeln** für Pferderegistrierung und -validierung
- **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

## 🚀 Aktuelle Optimierungen (2025-07-25)

Das Horses-Modul wurde kürzlich analysiert, vervollständigt und optimiert. Folgende Verbesserungen wurden implementiert:

### ✨ Neue Funktionalitäten

#### Erweiterte Such-Endpunkte
Neue REST-Endpunkte für vollständige Identifikationsnummer-Suche:
- `GET /api/horses/search/passport/{nummer}` - Suche nach Passnummer
- `GET /api/horses/search/oeps/{nummer}` - Suche nach OEPS-Nummer
- `GET /api/horses/search/fei/{nummer}` - Suche nach FEI-Nummer

#### Optimierte Statistik-Operationen
- Neue effiziente Zähl-Methoden für OEPS und FEI registrierte Pferde
- Performance-Verbesserung von O(n) auf O(1) Komplexität für Statistiken
- Datenbankoptimierte COUNT-Abfragen statt Laden aller Datensätze

### ⚡ Performance-Optimierungen

#### Datenbankeffizienz
- **Vorher**: Statistik-Endpunkt lud alle Pferde und verwendete `.size`
- **Nachher**: Effiziente COUNT-Abfragen direkt in der Datenbank
- **Auswirkung**: Drastische Reduzierung der Speichernutzung und Antwortzeiten

#### Architektur-Konsistenz
- Alle API-Endpunkte verwenden jetzt konsistent die Use-Case-Schicht
- Eliminierung direkter Repository-Aufrufe in der API-Schicht
- Saubere Trennung der Architektur-Schichten

### 🏗️ Architektur-Verbesserungen

#### Clean Architecture Compliance
- **Konsistente Schichtung**: Alle Endpunkte folgen dem Use-Case-Pattern
- **Fehlerbehandlung**: Einheitliche Fehlerantworten über alle Endpunkte
- **Validierung**: Umfassende Eingabevalidierung mit geteilten Utilities
- **HTTP-Standards**: Korrekte Status-Codes und REST-Konventionen

#### Code-Qualität
- Verbesserte Lesbarkeit und Wartbarkeit
- Konsistente Namenskonventionen
- Umfassende Dokumentation aller neuen Funktionen

### 📊 Qualitätsmetriken

#### Vor der Optimierung
- ❌ Fehlende Such-Endpunkte für 3 Identifikationstypen
- ❌ Ineffiziente Statistik-Abfragen (O(n) Komplexität)
- ❌ Inkonsistente Architektur (einige Endpunkte umgingen Use Cases)
- ❌ Performance-Probleme bei großen Datensätzen

#### Nach der Optimierung
- ✅ Vollständige API-Abdeckung für alle Identifikationstypen
- ✅ Effiziente Statistik-Abfragen (O(1) Komplexität)
- ✅ Konsistente Clean Architecture durchgehend
- ✅ Optimierte Performance für alle Operationen

### 🔮 Zukünftige Empfehlungen

#### Caching-Schicht
- Implementierung einer Caching-Schicht für häufig abgerufene Daten
- Individuelle Pferde-Lookups mit angemessener TTL
- Statistiken und Zählungen mit Cache-Invalidierung

#### Async-Operationen
- Asynchrone Verarbeitung für Batch-Operationen
- Komplexe Such-Abfragen mit Async-Pattern
- Statistik-Berechnungen im Hintergrund

#### Monitoring und Logging
- Umfassendes Monitoring für API-Antwortzeiten
- Datenbank-Query-Performance-Überwachung
- Fehlerrate-Tracking und -Analyse
- **DTO-Mapping** zwischen Domain und API
- **Validierung** und Fehlerbehandlung

### Service Layer
- **Spring Boot Anwendung**
- **Dependency Injection** Konfiguration
- **Integrationstests**

## Domain Model Details

### DomPferd-Entität

```kotlin
data class DomPferd(
    val pferdId: Uuid,

    // Grundinformationen
    var pferdeName: String,
    var geschlecht: PferdeGeschlechtE,
    var geburtsdatum: LocalDate? = null,
    var rasse: String? = null,
    var farbe: String? = null,

    // Besitz und Verantwortung
    var besitzerId: Uuid? = null,
    var verantwortlichePersonId: Uuid? = null,

    // Zuchtinformationen
    var zuechterName: String? = null,
    var zuchtbuchNummer: String? = null,

    // Identifikationsnummern
    var lebensnummer: String? = null,
    var chipNummer: String? = null,
    var passNummer: String? = null,
    var oepsNummer: String? = null,
    var feiNummer: String? = null,

    // Abstammung
    var vaterName: String? = null,
    var mutterName: String? = null,
    var mutterVaterName: String? = null,

    // Körperliche Merkmale
    var stockmass: Int? = null, // Höhe in cm

    // Status und Verwaltung
    var istAktiv: Boolean = true,
    var bemerkungen: String? = null,
    var datenQuelle: DatenQuelleE = DatenQuelleE.MANUELL,

    // Audit-Felder
    val createdAt: Instant,
    var updatedAt: Instant
)
```

### Geschäftslogik-Methoden

- `getDisplayName()` - Anzeigename mit Geburtsjahr
- `hasCompleteIdentification()` - Prüfung auf vollständige Identifikation
- `isOepsRegistered()` - OEPS-Registrierungsstatus
- `isFeiRegistered()` - FEI-Registrierungsstatus
- `getAge()` - Altersberechnung in Jahren
- `validateForRegistration()` - Validierung für Registrierung
- `withUpdatedTimestamp()` - Kopie mit aktualisiertem Zeitstempel

### Enumerationen

#### PferdeGeschlechtE
- `HENGST` - Hengst (männlich, nicht kastriert)
- `STUTE` - Stute (weiblich)
- `WALLACH` - Wallach (männlich, kastriert)

#### DatenQuelleE
- `MANUELL` - Manuelle Eingabe
- `IMPORT` - Datenimport
- `SYNCHRONISATION` - Synchronisation mit externen Systemen

## Repository-Operationen

### Erweiterte Such-Features

```kotlin
// Pferde nach Identifikationsnummer suchen
val horse = horseRepository.findByLebensnummer("AT123456789")
val chipHorse = horseRepository.findByChipNummer("982000123456789")

// Pferde eines Besitzers finden
val ownerHorses = horseRepository.findByOwnerId(ownerId, activeOnly = true)

// Pferde nach Eigenschaften filtern
val stallions = horseRepository.findByGeschlecht(PferdeGeschlechtE.HENGST)
val warmbloods = horseRepository.findByRasse("Warmblut", activeOnly = true)

// Pferde nach Geburtsjahr suchen
val youngHorses = horseRepository.findByBirthYearRange(2020, 2024)
```

### Registrierungs-Abfragen

```kotlin
// OEPS-registrierte Pferde finden
val oepsHorses = horseRepository.findOepsRegistered(activeOnly = true)

// FEI-registrierte Pferde finden
val feiHorses = horseRepository.findFeiRegistered(activeOnly = true)

// Alle aktiven Pferde
val activeHorses = horseRepository.findAllActive(limit = 1000)
```

### Validierung und Duplikatsprüfung

```kotlin
// Prüfung auf doppelte Identifikationsnummern
val lebensnummerExists = horseRepository.existsByLebensnummer("AT123456789")
val chipExists = horseRepository.existsByChipNummer("982000123456789")
val oepsExists = horseRepository.existsByOepsNummer("AUT12345")
```

## Use Cases

### CreateHorseUseCase

Erstellt ein neues Pferd mit Validierung und Duplikatsprüfung.

```kotlin
class CreateHorseUseCase(
    private val horseRepository: HorseRepository
) {
    suspend fun execute(horse: DomPferd): DomPferd {
        // Validierung
        val errors = horse.validateForRegistration()
        if (errors.isNotEmpty()) {
            throw ValidationException(errors)
        }

        // Duplikatsprüfung
        horse.lebensnummer?.let { nummer ->
            if (horseRepository.existsByLebensnummer(nummer)) {
                throw DuplicateException("Lebensnummer bereits vorhanden")
            }
        }

        return horseRepository.save(horse)
    }
}
```

### GetHorseUseCase

Ruft Pferdeinformationen ab mit verschiedenen Suchkriterien.

### UpdateHorseUseCase

Aktualisiert Pferdeinformationen mit Validierung.

### DeleteHorseUseCase

Löscht ein Pferd (soft delete durch Deaktivierung).

## API-Endpunkte

Das Horses-Modul stellt REST-Endpunkte über den HorseController bereit:

- `GET /api/horses` - Alle aktiven Pferde abrufen
- `GET /api/horses/{id}` - Pferd nach ID abrufen
- `GET /api/horses/search?name={name}` - Pferde nach Namen suchen
- `GET /api/horses/owner/{ownerId}` - Pferde eines Besitzers
- `GET /api/horses/identification/{number}` - Pferd nach Identifikationsnummer
- `GET /api/horses/oeps-registered` - OEPS-registrierte Pferde
- `GET /api/horses/fei-registered` - FEI-registrierte Pferde
- `POST /api/horses` - Neues Pferd erstellen
- `PUT /api/horses/{id}` - Pferd aktualisieren
- `DELETE /api/horses/{id}` - Pferd löschen

## Konfiguration

### Datenbankschema

Das Modul verwendet eine `horses`-Tabelle mit folgenden Spalten:
- `pferd_id` (UUID, Primary Key)
- `pferde_name` (Required)
- `geschlecht` (Enum: HENGST, STUTE, WALLACH)
- `geburtsdatum`, `rasse`, `farbe` (Optional)
- `besitzer_id`, `verantwortliche_person_id` (UUID, Foreign Keys)
- `zuechter_name`, `zuchtbuch_nummer` (Optional)
- `lebensnummer`, `chip_nummer`, `pass_nummer` (Unique, Optional)
- `oeps_nummer`, `fei_nummer` (Unique, Optional)
- `vater_name`, `mutter_name`, `mutter_vater_name` (Optional)
- `stockmass` (Integer, Optional)
- `ist_aktiv` (Boolean)
- `bemerkungen` (Text, Optional)
- `daten_quelle` (Enum)
- `created_at`, `updated_at` (Timestamps)

### Service-Konfiguration

```yaml
# application.yml
horses:
  service:
    name: horses-service
    port: 8083
  database:
    url: jdbc:postgresql://localhost:5432/meldestelle
    table: horses
  validation:
    require-identification: true
    allow-duplicate-names: false
```

## Tests

### Integration Tests

Das Modul enthält umfassende Integrationstests:

```kotlin
@Test
fun `should create horse with valid data`() {
    // Test für Pferdeerstellung
}

@Test
fun `should find horses by owner`() {
    // Test für Besitzer-basierte Suche
}

@Test
fun `should validate unique identification numbers`() {
    // Test für Eindeutigkeit der Identifikationsnummern
}
```

### Test-Datenbank

Verwendet H2 In-Memory-Datenbank für Tests mit automatischem Schema-Setup.

## Deployment

### Docker

```dockerfile
FROM openjdk:21-jre-slim
COPY horses-service.jar app.jar
EXPOSE 8083
ENTRYPOINT ["java", "-jar", "/app.jar"]
```

### Kubernetes

```yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: horses-service
spec:
  replicas: 2
  selector:
    matchLabels:
      app: horses-service
  template:
    spec:
      containers:
      - name: horses-service
        image: meldestelle/horses-service:latest
        ports:
        - containerPort: 8083
```

## Monitoring

### Metriken

- Anzahl aktiver Pferde
- Anzahl registrierter Pferde (OEPS/FEI)
- API-Response-Zeiten
- Datenbankverbindungs-Pool
- Validierungsfehler-Rate

### Health Checks

- Datenbankverbindung
- Service-Verfügbarkeit
- Speicherverbrauch
- Externe System-Verbindungen

## Entwicklung

### Lokale Entwicklung

```bash
# Service starten
./gradlew :horses:horses-service:bootRun

# Tests ausführen
./gradlew :horses:test

# Integration Tests
./gradlew :horses:horses-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

## Compliance und Standards

### OEPS-Integration

- Unterstützung für OEPS-Nummern
- Validierung nach OEPS-Standards
- Synchronisation mit OEPS-Datenbank

### FEI-Integration

- Unterstützung für FEI-Nummern
- Internationale Registrierungsstandards
- Compliance mit FEI-Regularien

### Datenschutz

- DSGVO-konforme Datenhaltung
- Anonymisierung von Testdaten
- Audit-Trail für alle Änderungen

## Zukünftige Erweiterungen

1. **Gesundheitsdaten** - Veterinärmedizinische Aufzeichnungen
2. **Leistungsdaten** - Turnierergebnisse und Bewertungen
3. **Versicherungsdaten** - Integration mit Versicherungssystemen
4. **Foto-Management** - Bildverwaltung für Pferde
5. **Stammbaum-Visualisierung** - Grafische Darstellung der Abstammung
6. **Import/Export** - Datenimport aus externen Systemen
7. **Mobile App** - Mobile Anwendung für Pferdebesitzer
8. **QR-Code-Integration** - QR-Codes für schnelle Identifikation

---

**Letzte Aktualisierung**: 25. Juli 2025

Für weitere Informationen zur Gesamtarchitektur siehe [README.md](../../README.md).
