Files
meldestelle/docs/api/members-api.md
T
stefan 65a0084f91 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)
2025-07-25 13:05:42 +02:00

623 lines
15 KiB
Markdown

# 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