docs: Migrationsplan für Projekt-Restrukturierung hinzugefügt

- Detaillierter Plan zur Migration von alter zu neuer Modulstruktur
- Umfasst Überführung von shared-kernel zu core-Modulen
- Definiert Migration von Fachdomänen zu bounded contexts:
  * master-data → masterdata-Module
  * member-management → members-Module
  * horse-registry → horses-Module
  * event-management → events-Module
- Beschreibt Verlagerung von api-gateway zu infrastructure/gateway
- Strukturiert nach Domain-driven Design Prinzipien
- Berücksichtigt Clean Architecture Layering (domain, application, infrastructure, api)
This commit is contained in:
stefan
2025-07-25 13:05:42 +02:00
parent a4c7d53aa3
commit 65a0084f91
68 changed files with 13107 additions and 101 deletions
+389
View File
@@ -0,0 +1,389 @@
# Meldestelle REST API Documentation
## Überblick
Die Meldestelle-Anwendung bietet eine umfassende REST API für die Verwaltung von Pferdesportveranstaltungen. Die API folgt RESTful-Prinzipien und ist in modulare Services unterteilt, die jeweils spezifische Domänen abdecken.
## API-Architektur
### Modulare Service-Struktur
Die API ist in folgende Hauptmodule unterteilt:
```
API Services
├── Members API # Mitgliederverwaltung
├── Horses API # Pferderegistrierung
├── Events API # Veranstaltungsverwaltung
└── Masterdata API # Stammdatenverwaltung
├── Countries # Länderverwaltung
├── States # Bundesländerverwaltung
├── Age Classes # Altersklassenverwaltung
└── Venues # Plätze/Austragungsorte
```
### Technische Spezifikationen
- **Framework**: Spring Boot 3.x mit Spring Web MVC
- **Dokumentation**: OpenAPI 3.0 (Swagger)
- **Serialisierung**: JSON mit Jackson/Kotlinx Serialization
- **Authentifizierung**: JWT Bearer Token
- **Versionierung**: URL-basiert (/api/v1/)
- **Content-Type**: application/json
- **Zeichenkodierung**: UTF-8
## Basis-URL und Endpunkte
### Entwicklungsumgebung
```
Base URL: http://localhost:8080/api
```
### Produktionsumgebung
```
Base URL: https://api.meldestelle.at/api
```
## API-Module Übersicht
### 1. Members API
**Basis-Pfad**: `/api/members`
Verwaltung von Vereinsmitgliedern und deren Mitgliedschaftsdaten.
**Hauptfunktionen**:
- Mitgliederverwaltung (CRUD)
- Mitgliedschaftsstatus-Tracking
- Ablaufende Mitgliedschaften
- Validierung von E-Mail und Mitgliedsnummer
**Controller**: `MemberController`
**Endpunkte**: 12 REST-Endpunkte
**Dokumentation**: [Members API](members-api.md)
### 2. Horses API
**Basis-Pfad**: `/api/horses`
Registrierung und Verwaltung von Pferden mit umfassenden Identifikationsdaten.
**Hauptfunktionen**:
- Pferderegistrierung (CRUD)
- Identifikationsnummern-Verwaltung
- OEPS/FEI-Registrierung
- Besitzer- und Verantwortlichen-Zuordnung
**Controller**: `HorseController`
**Endpunkte**: 15+ REST-Endpunkte
### 3. Events API
**Basis-Pfad**: `/api/events`
Planung und Verwaltung von Pferdesportveranstaltungen.
**Hauptfunktionen**:
- Veranstaltungsplanung (CRUD)
- Terminverwaltung
- Teilnehmerverwaltung
- Öffentliche/Private Veranstaltungen
**Controller**: `VeranstaltungController`
**Endpunkte**: 10+ REST-Endpunkte
### 4. Masterdata API
**Basis-Pfad**: `/api/masterdata`
Verwaltung von Stammdaten für das gesamte System.
#### 4.1 Countries API
**Pfad**: `/api/masterdata/countries`
- Länderverwaltung mit ISO-Codes
- EU/EWR-Mitgliedschaft
- Mehrsprachige Ländernamen
#### 4.2 States API
**Pfad**: `/api/masterdata/states`
- Bundesländer/Kantone/Regionen
- OEPS-Codes für österreichische Bundesländer
- ISO 3166-2 Codes
#### 4.3 Age Classes API
**Pfad**: `/api/masterdata/age-classes`
- Altersklassen für verschiedene Sparten
- Teilnahmeberechtigung
- Geschlechts- und Spartenfilter
#### 4.4 Venues API
**Pfad**: `/api/masterdata/venues`
- Turnierplätze und Austragungsorte
- Platztypen und Abmessungen
- Bodenarten und Eignung
**Controller**: `CountryController`, `BundeslandController`, `AltersklasseController`, `PlatzController`
**Endpunkte**: 37+ REST-Endpunkte
## Gemeinsame API-Konventionen
### HTTP-Status-Codes
| Status Code | Bedeutung | Verwendung |
|-------------|-----------|------------|
| 200 | OK | Erfolgreiche GET/PUT-Anfragen |
| 201 | Created | Erfolgreiche POST-Anfragen |
| 204 | No Content | Erfolgreiche DELETE-Anfragen |
| 400 | Bad Request | Ungültige Anfragedaten |
| 401 | Unauthorized | Fehlende/ungültige Authentifizierung |
| 403 | Forbidden | Unzureichende Berechtigung |
| 404 | Not Found | Ressource nicht gefunden |
| 409 | Conflict | Duplikat oder Geschäftsregel-Verletzung |
| 422 | Unprocessable Entity | Validierungsfehler |
| 500 | Internal Server Error | Serverfehler |
### Standard-Response-Format
Alle API-Endpunkte verwenden ein einheitliches Response-Format:
```json
{
"data": {},
"success": true,
"message": "Operation completed successfully",
"errors": [],
"timestamp": "2025-07-25T12:37:00Z"
}
```
#### Erfolgreiche Antwort
```json
{
"data": {
"id": "123e4567-e89b-12d3-a456-426614174000",
"firstName": "Max",
"lastName": "Mustermann",
"email": "max@example.com"
},
"success": true,
"message": null,
"errors": [],
"timestamp": "2025-07-25T12:37:00Z"
}
```
#### Fehler-Antwort
```json
{
"data": null,
"success": false,
"message": "Validation failed",
"errors": [
"Email address is required",
"First name must not be empty"
],
"timestamp": "2025-07-25T12:37:00Z"
}
```
### Paginierung
Für Listen-Endpunkte wird standardmäßig Paginierung unterstützt:
**Query-Parameter**:
- `limit`: Maximale Anzahl Ergebnisse (Standard: 100, Maximum: 1000)
- `offset`: Anzahl zu überspringende Ergebnisse (Standard: 0)
**Beispiel-Anfrage**:
```
GET /api/members?limit=50&offset=100
```
**Paginierte Antwort**:
```json
{
"data": {
"content": [],
"page": 2,
"size": 50,
"totalElements": 1250,
"totalPages": 25,
"hasNext": true,
"hasPrevious": true
},
"success": true,
"timestamp": "2025-07-25T12:37:00Z"
}
```
### Suchfunktionalität
Viele Endpunkte unterstützen Suchfunktionalität:
**Query-Parameter**:
- `search`: Suchbegriff für Textfelder
- `name`: Suche nach Namen (Teilübereinstimmung)
- `active`: Filter für aktive/inaktive Einträge
**Beispiel**:
```
GET /api/members?search=Schmidt&active=true&limit=20
```
### Sortierung
Sortierung wird über Query-Parameter gesteuert:
**Query-Parameter**:
- `sort`: Sortierfeld (z.B. `name`, `createdAt`)
- `order`: Sortierrichtung (`asc` oder `desc`)
**Beispiel**:
```
GET /api/members?sort=lastName&order=asc
```
## Authentifizierung und Autorisierung
### JWT Bearer Token
Alle API-Endpunkte (außer öffentlichen) erfordern Authentifizierung über JWT Bearer Token:
```http
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
### Rollen und Berechtigungen
| Rolle | Beschreibung | Berechtigungen |
|-------|--------------|----------------|
| ADMIN | Systemadministrator | Vollzugriff auf alle Ressourcen |
| TRAINER | Trainer/Ausbilder | Zugriff auf Pferde und Veranstaltungen |
| MEMBER | Vereinsmitglied | Zugriff auf eigene Daten |
| GUEST | Gast | Nur Lesezugriff auf öffentliche Daten |
## Rate Limiting
Zum Schutz der API vor Überlastung gelten folgende Limits:
- **Authentifizierte Benutzer**: 1000 Anfragen/Stunde
- **Nicht authentifizierte Benutzer**: 100 Anfragen/Stunde
- **Burst-Limit**: 50 Anfragen/Minute
Bei Überschreitung wird HTTP 429 (Too Many Requests) zurückgegeben.
## Fehlerbehandlung
### Validierungsfehler (422)
```json
{
"data": null,
"success": false,
"message": "Validation failed",
"errors": [
{
"field": "email",
"message": "Email address is invalid",
"code": "INVALID_EMAIL"
},
{
"field": "membershipNumber",
"message": "Membership number already exists",
"code": "DUPLICATE_MEMBERSHIP_NUMBER"
}
],
"timestamp": "2025-07-25T12:37:00Z"
}
```
### Geschäftsregel-Verletzungen (409)
```json
{
"data": null,
"success": false,
"message": "Business rule violation",
"errors": [
"Membership end date cannot be before start date"
],
"timestamp": "2025-07-25T12:37:00Z"
}
```
## API-Dokumentation
### Swagger/OpenAPI
Die vollständige API-Dokumentation ist über Swagger UI verfügbar:
- **Entwicklung**: http://localhost:8080/swagger-ui.html
- **Produktion**: https://api.meldestelle.at/swagger-ui.html
### Postman Collections
Postman Collections für alle API-Endpunkte sind verfügbar unter:
- [docs/postman/](../postman/)
## Versionierung
Die API verwendet URL-basierte Versionierung:
- **Aktuelle Version**: v1
- **Basis-URL**: `/api/v1/`
- **Deprecated Versionen**: Werden 12 Monate unterstützt
## Monitoring und Observability
### Health Checks
```
GET /actuator/health
```
### Metriken
```
GET /actuator/metrics
GET /actuator/prometheus
```
### API-Metriken
- Request-Anzahl pro Endpunkt
- Response-Zeiten
- Fehlerquoten
- Rate-Limiting-Statistiken
## Entwicklung und Testing
### Lokale Entwicklung
```bash
# API-Server starten
./gradlew bootRun
# Swagger UI öffnen
open http://localhost:8080/swagger-ui.html
```
### API-Tests
```bash
# Unit Tests
./gradlew test
# Integration Tests
./gradlew integrationTest
# API Tests mit Newman
newman run docs/postman/meldestelle-api.postman_collection.json
```
## Support und Kontakt
- **Dokumentation**: [docs/api/](.)
- **Issue Tracker**: GitHub Issues
- **API-Status**: https://status.meldestelle.at
---
**Letzte Aktualisierung**: 25. Juli 2025
**API-Version**: v1.0
**OpenAPI-Spezifikation**: 3.0.3
+36
View File
@@ -0,0 +1,36 @@
{
"openapi": "3.0.3",
"info": {
"title": "Events API",
"description": "REST API for events management",
"version": "1.0.0",
"contact": {
"name": "Meldestelle Development Team"
}
},
"servers": [
{
"url": "http://localhost:8080",
"description": "Development server"
},
{
"url": "https://api.meldestelle.at",
"description": "Production server"
}
],
"paths": {},
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"security": [
{
"bearerAuth": []
}
]
}
+36
View File
@@ -0,0 +1,36 @@
{
"openapi": "3.0.3",
"info": {
"title": "Horses API",
"description": "REST API for horses management",
"version": "1.0.0",
"contact": {
"name": "Meldestelle Development Team"
}
},
"servers": [
{
"url": "http://localhost:8080",
"description": "Development server"
},
{
"url": "https://api.meldestelle.at",
"description": "Production server"
}
],
"paths": {},
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"security": [
{
"bearerAuth": []
}
]
}
@@ -0,0 +1,36 @@
{
"openapi": "3.0.3",
"info": {
"title": "Masterdata API",
"description": "REST API for masterdata management",
"version": "1.0.0",
"contact": {
"name": "Meldestelle Development Team"
}
},
"servers": [
{
"url": "http://localhost:8080",
"description": "Development server"
},
{
"url": "https://api.meldestelle.at",
"description": "Production server"
}
],
"paths": {},
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"security": [
{
"bearerAuth": []
}
]
}
+36
View File
@@ -0,0 +1,36 @@
{
"openapi": "3.0.3",
"info": {
"title": "Members API",
"description": "REST API for members management",
"version": "1.0.0",
"contact": {
"name": "Meldestelle Development Team"
}
},
"servers": [
{
"url": "http://localhost:8080",
"description": "Development server"
},
{
"url": "https://api.meldestelle.at",
"description": "Production server"
}
],
"paths": {},
"components": {
"securitySchemes": {
"bearerAuth": {
"type": "http",
"scheme": "bearer",
"bearerFormat": "JWT"
}
}
},
"security": [
{
"bearerAuth": []
}
]
}
+622
View File
@@ -0,0 +1,622 @@
# Members API Documentation
## Überblick
Die Members API bietet umfassende Funktionalität zur Verwaltung von Vereinsmitgliedern und deren Mitgliedschaftsdaten. Sie unterstützt vollständige CRUD-Operationen sowie spezialisierte Funktionen für Mitgliedschaftsverwaltung, Validierung und Statistiken.
## Basis-Informationen
- **Basis-URL**: `/api/members`
- **Controller**: `MemberController`
- **Authentifizierung**: JWT Bearer Token erforderlich
- **Content-Type**: `application/json`
- **Zeichenkodierung**: UTF-8
## Endpunkte Übersicht
| Methode | Endpunkt | Beschreibung |
|---------|----------|--------------|
| GET | `/api/members` | Alle Mitglieder abrufen |
| GET | `/api/members/{id}` | Mitglied nach ID abrufen |
| GET | `/api/members/by-membership-number/{membershipNumber}` | Mitglied nach Mitgliedsnummer |
| GET | `/api/members/by-email/{email}` | Mitglied nach E-Mail |
| GET | `/api/members/stats` | Mitgliederstatistiken |
| POST | `/api/members` | Neues Mitglied erstellen |
| PUT | `/api/members/{id}` | Mitglied aktualisieren |
| DELETE | `/api/members/{id}` | Mitglied löschen |
| GET | `/api/members/expiring-memberships` | Ablaufende Mitgliedschaften |
| GET | `/api/members/by-date-range` | Mitglieder nach Datumsbereich |
| GET | `/api/members/validate/email/{email}` | E-Mail-Eindeutigkeit prüfen |
| GET | `/api/members/validate/membership-number/{membershipNumber}` | Mitgliedsnummer-Eindeutigkeit prüfen |
## Detaillierte Endpunkt-Dokumentation
### 1. Alle Mitglieder abrufen
```http
GET /api/members
```
Ruft eine Liste aller Mitglieder ab mit optionaler Filterung und Suche.
#### Query-Parameter
| Parameter | Typ | Standard | Beschreibung |
|-----------|-----|----------|--------------|
| `activeOnly` | boolean | `true` | Nur aktive Mitglieder anzeigen |
| `limit` | integer | `100` | Maximale Anzahl Ergebnisse |
| `offset` | integer | `0` | Anzahl zu überspringende Ergebnisse |
| `search` | string | - | Suchbegriff für Mitgliedernamen |
#### Beispiel-Anfrage
```http
GET /api/members?activeOnly=true&limit=50&search=Schmidt
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
#### Erfolgreiche Antwort (200 OK)
```json
{
"data": [
{
"memberId": "123e4567-e89b-12d3-a456-426614174000",
"firstName": "Max",
"lastName": "Schmidt",
"email": "max.schmidt@example.com",
"phone": "+43 1 234 5678",
"dateOfBirth": "1985-03-15",
"membershipNumber": "M2024001",
"membershipStartDate": "2024-01-01",
"membershipEndDate": "2024-12-31",
"isActive": true,
"address": "Musterstraße 123, 1010 Wien",
"emergencyContact": "Anna Schmidt, +43 1 234 5679",
"createdAt": "2024-01-01T10:00:00Z",
"updatedAt": "2024-07-25T12:37:00Z"
}
],
"success": true,
"message": null,
"errors": [],
"timestamp": "2025-07-25T12:37:00Z"
}
```
#### Fehler-Antworten
- **500 Internal Server Error**: Serverfehler beim Abrufen der Mitglieder
### 2. Mitglied nach ID abrufen
```http
GET /api/members/{id}
```
Ruft ein spezifisches Mitglied anhand seiner eindeutigen ID ab.
#### Pfad-Parameter
| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `id` | UUID | Eindeutige Mitglieder-ID |
#### Beispiel-Anfrage
```http
GET /api/members/123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
#### Erfolgreiche Antwort (200 OK)
```json
{
"data": {
"memberId": "123e4567-e89b-12d3-a456-426614174000",
"firstName": "Max",
"lastName": "Schmidt",
"email": "max.schmidt@example.com",
"phone": "+43 1 234 5678",
"dateOfBirth": "1985-03-15",
"membershipNumber": "M2024001",
"membershipStartDate": "2024-01-01",
"membershipEndDate": "2024-12-31",
"isActive": true,
"address": "Musterstraße 123, 1010 Wien",
"emergencyContact": "Anna Schmidt, +43 1 234 5679",
"createdAt": "2024-01-01T10:00:00Z",
"updatedAt": "2024-07-25T12:37:00Z"
},
"success": true,
"message": null,
"errors": [],
"timestamp": "2025-07-25T12:37:00Z"
}
```
#### Fehler-Antworten
- **400 Bad Request**: Ungültiges UUID-Format
- **404 Not Found**: Mitglied nicht gefunden
- **500 Internal Server Error**: Serverfehler
### 3. Mitglied nach Mitgliedsnummer abrufen
```http
GET /api/members/by-membership-number/{membershipNumber}
```
#### Pfad-Parameter
| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `membershipNumber` | string | Mitgliedsnummer |
#### Beispiel-Anfrage
```http
GET /api/members/by-membership-number/M2024001
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
### 4. Mitglied nach E-Mail abrufen
```http
GET /api/members/by-email/{email}
```
#### Pfad-Parameter
| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `email` | string | E-Mail-Adresse |
#### Beispiel-Anfrage
```http
GET /api/members/by-email/max.schmidt@example.com
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
### 5. Mitgliederstatistiken abrufen
```http
GET /api/members/stats
```
Ruft Statistiken über die Mitgliederdatenbank ab.
#### Erfolgreiche Antwort (200 OK)
```json
{
"data": {
"totalActive": 1250,
"totalMembers": 1380
},
"success": true,
"message": null,
"errors": [],
"timestamp": "2025-07-25T12:37:00Z"
}
```
### 6. Neues Mitglied erstellen
```http
POST /api/members
```
Erstellt ein neues Mitglied mit den bereitgestellten Daten.
#### Request Body
```json
{
"firstName": "Max",
"lastName": "Mustermann",
"email": "max.mustermann@example.com",
"phone": "+43 1 234 5678",
"dateOfBirth": "1985-03-15",
"membershipNumber": "M2024002",
"membershipStartDate": "2024-08-01",
"membershipEndDate": "2024-12-31",
"isActive": true,
"address": "Beispielstraße 456, 1020 Wien",
"emergencyContact": "Anna Mustermann, +43 1 234 5679"
}
```
#### Erfolgreiche Antwort (201 Created)
```json
{
"data": {
"memberId": "456e7890-e89b-12d3-a456-426614174001",
"firstName": "Max",
"lastName": "Mustermann",
"email": "max.mustermann@example.com",
"phone": "+43 1 234 5678",
"dateOfBirth": "1985-03-15",
"membershipNumber": "M2024002",
"membershipStartDate": "2024-08-01",
"membershipEndDate": "2024-12-31",
"isActive": true,
"address": "Beispielstraße 456, 1020 Wien",
"emergencyContact": "Anna Mustermann, +43 1 234 5679",
"createdAt": "2025-07-25T12:37:00Z",
"updatedAt": "2025-07-25T12:37:00Z"
},
"success": true,
"message": null,
"errors": [],
"timestamp": "2025-07-25T12:37:00Z"
}
```
#### Fehler-Antworten
- **400 Bad Request**: Ungültige Anfragedaten
- **409 Conflict**: E-Mail oder Mitgliedsnummer bereits vorhanden
- **422 Unprocessable Entity**: Validierungsfehler
### 7. Mitglied aktualisieren
```http
PUT /api/members/{id}
```
Aktualisiert ein bestehendes Mitglied.
#### Pfad-Parameter
| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `id` | UUID | Eindeutige Mitglieder-ID |
#### Request Body
```json
{
"firstName": "Max",
"lastName": "Mustermann",
"email": "max.mustermann.updated@example.com",
"phone": "+43 1 234 5678",
"dateOfBirth": "1985-03-15",
"membershipNumber": "M2024002",
"membershipStartDate": "2024-08-01",
"membershipEndDate": "2025-07-31",
"isActive": true,
"address": "Neue Straße 789, 1030 Wien",
"emergencyContact": "Anna Mustermann, +43 1 234 5679"
}
```
#### Erfolgreiche Antwort (200 OK)
Gleiche Struktur wie bei der Erstellung, aber mit aktualisierten Daten und `updatedAt` Zeitstempel.
#### Fehler-Antworten
- **400 Bad Request**: Ungültige Anfragedaten oder UUID-Format
- **404 Not Found**: Mitglied nicht gefunden
- **409 Conflict**: E-Mail oder Mitgliedsnummer bereits vorhanden
- **500 Internal Server Error**: Serverfehler
### 8. Mitglied löschen
```http
DELETE /api/members/{id}
```
Löscht ein Mitglied aus dem System.
#### Pfad-Parameter
| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `id` | UUID | Eindeutige Mitglieder-ID |
#### Beispiel-Anfrage
```http
DELETE /api/members/123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
#### Erfolgreiche Antwort (200 OK)
```json
{
"data": "Member deleted successfully",
"success": true,
"message": null,
"errors": [],
"timestamp": "2025-07-25T12:37:00Z"
}
```
#### Fehler-Antworten
- **400 Bad Request**: Ungültiges UUID-Format
- **404 Not Found**: Mitglied nicht gefunden
- **500 Internal Server Error**: Serverfehler
### 9. Ablaufende Mitgliedschaften abrufen
```http
GET /api/members/expiring-memberships
```
Ruft Mitglieder ab, deren Mitgliedschaft in den nächsten Tagen abläuft.
#### Query-Parameter
| Parameter | Typ | Standard | Beschreibung |
|-----------|-----|----------|--------------|
| `daysAhead` | integer | `30` | Anzahl Tage im Voraus |
#### Beispiel-Anfrage
```http
GET /api/members/expiring-memberships?daysAhead=14
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
#### Erfolgreiche Antwort (200 OK)
```json
{
"data": [
{
"memberId": "123e4567-e89b-12d3-a456-426614174000",
"firstName": "Max",
"lastName": "Schmidt",
"email": "max.schmidt@example.com",
"membershipNumber": "M2024001",
"membershipEndDate": "2025-08-10",
"daysUntilExpiry": 14
}
],
"success": true,
"message": null,
"errors": [],
"timestamp": "2025-07-25T12:37:00Z"
}
```
### 10. Mitglieder nach Datumsbereich abrufen
```http
GET /api/members/by-date-range
```
Ruft Mitglieder basierend auf einem Datumsbereich ab.
#### Query-Parameter
| Parameter | Typ | Erforderlich | Beschreibung |
|-----------|-----|--------------|--------------|
| `startDate` | string (YYYY-MM-DD) | Ja | Startdatum |
| `endDate` | string (YYYY-MM-DD) | Ja | Enddatum |
| `dateType` | string | Nein | `MEMBERSHIP_START_DATE` oder `MEMBERSHIP_END_DATE` |
#### Beispiel-Anfrage
```http
GET /api/members/by-date-range?startDate=2024-01-01&endDate=2024-12-31&dateType=MEMBERSHIP_START_DATE
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
#### Fehler-Antworten
- **400 Bad Request**: Ungültiges Datumsformat oder Datumstyp
### 11. E-Mail-Eindeutigkeit validieren
```http
GET /api/members/validate/email/{email}
```
Prüft, ob eine E-Mail-Adresse bereits verwendet wird.
#### Pfad-Parameter
| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `email` | string | Zu prüfende E-Mail-Adresse |
#### Query-Parameter
| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `excludeMemberId` | UUID | Mitglieder-ID zum Ausschließen (für Updates) |
#### Beispiel-Anfrage
```http
GET /api/members/validate/email/test@example.com?excludeMemberId=123e4567-e89b-12d3-a456-426614174000
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...
```
#### Erfolgreiche Antwort (200 OK)
```json
{
"data": {
"isValid": true,
"isUnique": false,
"message": "Email address is already in use"
},
"success": true,
"message": null,
"errors": [],
"timestamp": "2025-07-25T12:37:00Z"
}
```
### 12. Mitgliedsnummer-Eindeutigkeit validieren
```http
GET /api/members/validate/membership-number/{membershipNumber}
```
Prüft, ob eine Mitgliedsnummer bereits verwendet wird.
#### Pfad-Parameter
| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `membershipNumber` | string | Zu prüfende Mitgliedsnummer |
#### Query-Parameter
| Parameter | Typ | Beschreibung |
|-----------|-----|--------------|
| `excludeMemberId` | UUID | Mitglieder-ID zum Ausschließen (für Updates) |
## Datenmodelle
### Member (Mitglied)
```json
{
"memberId": "UUID",
"firstName": "string",
"lastName": "string",
"email": "string",
"phone": "string (optional)",
"dateOfBirth": "string (YYYY-MM-DD, optional)",
"membershipNumber": "string",
"membershipStartDate": "string (YYYY-MM-DD)",
"membershipEndDate": "string (YYYY-MM-DD, optional)",
"isActive": "boolean",
"address": "string (optional)",
"emergencyContact": "string (optional)",
"createdAt": "string (ISO 8601)",
"updatedAt": "string (ISO 8601)"
}
```
### CreateMemberRequest
```json
{
"firstName": "string (required)",
"lastName": "string (required)",
"email": "string (required)",
"phone": "string (optional)",
"dateOfBirth": "string (YYYY-MM-DD, optional)",
"membershipNumber": "string (required)",
"membershipStartDate": "string (YYYY-MM-DD, required)",
"membershipEndDate": "string (YYYY-MM-DD, optional)",
"isActive": "boolean (default: true)",
"address": "string (optional)",
"emergencyContact": "string (optional)"
}
```
### UpdateMemberRequest
Identisch mit `CreateMemberRequest`.
### MemberStats
```json
{
"totalActive": "number",
"totalMembers": "number"
}
```
## Validierungsregeln
### Pflichtfelder
- `firstName`: Nicht leer
- `lastName`: Nicht leer
- `email`: Gültige E-Mail-Adresse, eindeutig
- `membershipNumber`: Nicht leer, eindeutig
- `membershipStartDate`: Gültiges Datum
### Geschäftsregeln
- E-Mail-Adresse muss eindeutig sein
- Mitgliedsnummer muss eindeutig sein
- `membershipEndDate` muss nach `membershipStartDate` liegen (falls angegeben)
- Telefonnummer muss gültiges Format haben (falls angegeben)
## Fehlerbehandlung
### Validierungsfehler (422 Unprocessable Entity)
```json
{
"data": null,
"success": false,
"message": "Validation failed",
"errors": [
{
"field": "email",
"message": "Email address is invalid",
"code": "INVALID_EMAIL"
},
{
"field": "membershipNumber",
"message": "Membership number already exists",
"code": "DUPLICATE_MEMBERSHIP_NUMBER"
}
],
"timestamp": "2025-07-25T12:37:00Z"
}
```
### Häufige Fehlercodes
| Code | Beschreibung |
|------|--------------|
| `MEMBER_NOT_FOUND` | Mitglied nicht gefunden |
| `INVALID_EMAIL` | Ungültige E-Mail-Adresse |
| `DUPLICATE_EMAIL` | E-Mail bereits vorhanden |
| `DUPLICATE_MEMBERSHIP_NUMBER` | Mitgliedsnummer bereits vorhanden |
| `INVALID_DATE_FORMAT` | Ungültiges Datumsformat |
| `INVALID_UUID_FORMAT` | Ungültiges UUID-Format |
| `MEMBERSHIP_DATE_CONFLICT` | Enddatum vor Startdatum |
## Beispiel-Workflows
### Neues Mitglied registrieren
1. **E-Mail validieren**: `GET /api/members/validate/email/{email}`
2. **Mitgliedsnummer validieren**: `GET /api/members/validate/membership-number/{membershipNumber}`
3. **Mitglied erstellen**: `POST /api/members`
### Mitglied aktualisieren
1. **Aktuelles Mitglied abrufen**: `GET /api/members/{id}`
2. **E-Mail validieren** (falls geändert): `GET /api/members/validate/email/{email}?excludeMemberId={id}`
3. **Mitglied aktualisieren**: `PUT /api/members/{id}`
### Ablaufende Mitgliedschaften verwalten
1. **Ablaufende Mitgliedschaften abrufen**: `GET /api/members/expiring-memberships?daysAhead=30`
2. **Für jedes Mitglied**: Benachrichtigung senden oder Verlängerung anbieten
## Rate Limiting
- **Authentifizierte Anfragen**: 1000 Anfragen/Stunde
- **Validierungs-Endpunkte**: 100 Anfragen/Minute (zusätzliches Limit)
## Caching
- **GET-Anfragen**: 5 Minuten Cache (außer Validierungs-Endpunkte)
- **Statistiken**: 15 Minuten Cache
- **Cache-Invalidierung**: Bei POST/PUT/DELETE-Operationen
---
**Letzte Aktualisierung**: 25. Juli 2025
**API-Version**: v1.0
**Controller-Version**: MemberController v1.0