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:
@@ -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
|
||||
@@ -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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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": []
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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
|
||||
Reference in New Issue
Block a user