Update README.md with comprehensive documentation of Advoware Calendar Sync implementation, including API quirks, token security, and known issues

This commit is contained in:
root
2025-10-22 23:36:21 +00:00
parent c897f4c39d
commit 0a4317c44a

View File

@@ -13,35 +13,69 @@ Das System synchronisiert Termine zwischen:
### Automatische Kalender-Erstellung
- Für jeden Advoware-Mitarbeiter wird ein Google Calendar mit dem Namen `AW-{Kuerzel}` erstellt
- Beispiel: Mitarbeiter mit Kürzel "SB" → Calendar "AW-SB"
- Kalender wird mit dem Haupt-Google-Account (`lehmannundpartner@gmail.com`) als Owner geteilt
### Bidirektionale Synchronisation
### Bidirektionale Synchronisation mit Token-Validierung
#### Advoware → Google Calendar
- Alle Termine eines Mitarbeiters werden aus Advoware abgerufen
- Alle Termine eines Mitarbeiters werden aus Advoware abgerufen (Zeitraum: aktuelles Jahr + 2 Jahre)
- Neue Termine werden in den entsprechenden Google Calendar eingetragen
- Die Advoware-Termin-ID (`frNr`) wird als Metadaten gespeichert
- Bestehende Termine werden aktualisiert, wenn Änderungen erkannt werden
#### Google Calendar → Advoware
- Termine aus Google Calendar ohne `frNr` werden als neue Termine in Advoware erstellt
- Die generierte `frNr` wird zurück in den Google Calendar geschrieben
- Token-basierte Validierung verhindert unbefugte Änderungen
- Sync-Info wird in der Description/Notiz gespeichert
### Konfigurationsoptionen
- **Vollständige Termindetails**: Titel, Beschreibung, Ort werden synchronisiert
- **Nur "Blocked"**: Termine werden nur als "beschäftigt" markiert (keine Details)
### Token-Sicherheit
- MD5-Hash mit Salt (aus Umgebungsvariable `CALENDAR_SYNC_SALT`) für Änderungsvalidierung
- Sync-Info Format: `## no change below this line ##\nfrNr: {frNr}\nsync-token: {token}`
- Token wird bei jeder Änderung neu berechnet und validiert
### Löschungen
- Google-initiale Termine, die in Google gelöscht werden, werden auch in Advoware gelöscht
- Tracking von gelöschten `frNr` um Re-Sync zu verhindern
## API-Endpunkte
### Advoware
- `GET /api/v1/advonet/Mitarbeiter` - Liste aller Mitarbeiter
### Advoware API
- `GET /api/v1/advonet/Mitarbeiter?aktiv=true` - Liste aktiver Mitarbeiter
- `GET /api/v1/advonet/Termine?frnr={frnr}` - Einzelner Termin
- `GET /api/v1/advonet/Termine?kuerzel={kuerzel}&from={date}&to={date}` - Termine eines Mitarbeiters
- `POST /api/v1/advonet/Termine` - Neuen Termin erstellen
- `PUT /api/v1/advonet/Termine` - Termin aktualisieren
- `DELETE /api/v1/advonet/Termine?frnr={frnr}` - Termin löschen
**API-Schwächen und Seltsamkeiten:**
- Parameter müssen als Strings übergeben werden (z.B. `aktiv='true'`, nicht `True`)
- Response kann manchmal HTML statt JSON zurückgeben, auch bei 200 Status
- Content-Type Header ist nicht immer korrekt gesetzt
- Token-Authentifizierung mit HMAC-Signature erforderlich
- Keine Paginierung für große Resultate
- Zeitformate: `datum` als `YYYY-MM-DDTHH:MM:SS`, aber manchmal ohne T
### Google Calendar API
- Kalender-Management (erstellen, auflisten)
- Kalender-Management (erstellen, auflisten, ACL setzen)
- Event-Management (erstellen, aktualisieren, löschen)
- Service Account Authentifizierung mit Backoff bei Rate Limits
## Step-Konfiguration
### advoware_calendar_sync_step.py
### calendar_sync_event_step.py
- **Type:** event
- **Subscribes:** calendar.sync.triggered
- **Flows:** advoware
**Event Data:**
```json
{
"full_content": true // oder false für nur "blocked"
}
```
### calendar_sync_api_step.py
- **Type:** api
- **Path:** `/advoware/calendar/sync`
- **Method:** POST
@@ -54,17 +88,48 @@ Das System synchronisiert Termine zwischen:
}
```
### calendar_sync_cron_step.py
- **Type:** cron
- **Schedule:** Täglich um 2:00 Uhr
- **Flows:** advoware
## Setup
### Google API Credentials
1. Google Cloud Console Projekt erstellen
2. Google Calendar API aktivieren
3. OAuth 2.0 Credentials erstellen
4. `token.pickle` Datei im Projektverzeichnis bereitstellen
3. Service Account erstellen (kein OAuth)
4. `service-account.json` Datei im Projektverzeichnis bereitstellen
### Advoware API Credentials
OAuth-ähnliche Authentifizierung mit HMAC-Signature.
### Umgebungsvariablen
```env
GOOGLE_CALENDAR_CREDENTIALS_PATH=token.pickle
# Google Calendar
GOOGLE_CALENDAR_SERVICE_ACCOUNT_PATH=service-account.json
# Advoware API
ADVOWARE_API_BASE_URL=https://www2.advo-net.net:90/
ADVOWARE_PRODUCT_ID=64
ADVOWARE_APP_ID=your_app_id
ADVOWARE_API_KEY=your_api_key
ADVOWARE_KANZLEI=your_kanzlei
ADVOWARE_DATABASE=your_database
ADVOWARE_USER=your_user
ADVOWARE_ROLE=2
ADVOWARE_PASSWORD=your_password
ADVOWARE_TOKEN_LIFETIME_MINUTES=55
ADVOWARE_API_TIMEOUT_SECONDS=30
# Redis für Token Caching
REDIS_HOST=localhost
REDIS_PORT=6379
REDIS_DB_ADVOWARE_CACHE=1
REDIS_TIMEOUT_SECONDS=5
# Calendar Sync
CALENDAR_SYNC_SALT=your_secret_salt
```
## Verwendung
@@ -76,28 +141,35 @@ curl -X POST "http://localhost:3000/advoware/calendar/sync" \
-d '{"full_content": true}'
```
### Event-basierter Sync
```bash
curl -X POST "http://localhost:3000/events" \
-H "Content-Type: application/json" \
-d '{"type": "calendar.sync.triggered", "data": {"full_content": true}}'
```
### Automatischer Sync
Der Step kann über Cron-Jobs oder Events regelmäßig ausgeführt werden.
Der Cron-Step führt täglich um 2:00 Uhr einen vollständigen Sync aus.
## Datenmapping
### Advoware → Google Calendar
```javascript
{
"summary": appointment.text || "Advoware Termin",
"description": `Advoware Termin\nNotiz: ${appointment.notiz}\nOrt: ${appointment.ort}`,
"location": appointment.ort,
"summary": "Advoware blocked", // Immer "blocked" für Privacy
"description": `Advoware Termin ID: ${appointment.frNr}`,
"location": "",
"start": {
"dateTime": `${appointment.datum}T${appointment.uhrzeitBis || '00:00:00'}`,
"dateTime": start_datetime, // Berechnet aus datum/uhrzeitVon
"timeZone": "Europe/Berlin"
},
"end": {
"dateTime": `${appointment.datumBis || appointment.datum}T${appointment.uhrzeitBis || '23:59:59'}`,
"dateTime": end_datetime, // Berechnet aus datumBis/uhrzeitBis
"timeZone": "Europe/Berlin"
},
"extendedProperties": {
"private": {
"advoware_frnr": appointment.frNr
"advoware_frnr": appointment.frNr.toString()
}
}
}
@@ -106,56 +178,84 @@ Der Step kann über Cron-Jobs oder Events regelmäßig ausgeführt werden.
### Google Calendar → Advoware
```javascript
{
"frNr": int(frnr),
"text": event.summary,
"notiz": event.description,
"notiz": updated_description, // Mit sync-info
"ort": event.location,
"datum": event.start.dateTime.substring(0, 10),
"uhrzeitBis": event.start.dateTime.substring(11, 19),
"datumBis": event.end.dateTime.substring(0, 10),
"datum": start.split('+')[0] if '+' in start else start,
"uhrzeitBis": end.split('T')[1].split('+')[0] if 'T' in end else '09:00:00',
"datumBis": end.split('+')[0] if '+' in end else end,
"sb": employee_kuerzel,
"anwalt": employee_kuerzel
"anwalt": employee_kuerzel,
"vorbereitungsDauer": "00:00:00"
}
```
## Fehlerbehandlung
- **Google API Fehler:** Automatische Token-Refresh, Fallback bei Authentifizierungsfehlern
- **Advoware API Fehler:** Retry-Logic, detaillierte Logging
- **Netzwerkfehler:** Timeout-Handling, Wiederholungsversuche
- **Dateninkonsistenzen:** Validierung vor Sync, Konfliktlösung
- **Google API Fehler:** Exponentieller Backoff bei 403/429, automatische Wiederholung
- **Advoware API Fehler:** Token-Refresh bei 401, detaillierte Logging
- **JSON Parse Fehler:** Response-Text logging für Debugging
- **Netzwerkfehler:** Timeout-Handling, konfigurierbare Timeouts
- **Dateninkonsistenzen:** Token-Validierung, Änderungsvergleich vor Update
## Monitoring
### Logs
- Erfolgreiche Synchronisationen
- Fehlerhafte Termine
- Kalender-Erstellungen
- Performance-Metriken
- Erfolgreiche Synchronisationen mit Anzahl
- Fehlerhafte API-Calls mit Details
- Kalender-Erstellungen und ACL-Setups
- Performance-Metriken (Sync-Dauer)
- Debug-Logs für Änderungsvergleiche
### Metriken
- Anzahl synchronisierter Termine
- Verarbeitete Mitarbeiter
- Fehlerquoten
- Sync-Dauer
- Fehlerquoten pro API
- Gelöschte Termine
- Token-Validierungsfehler
## Sicherheit
- OAuth 2.0 für Google API Zugriff
- Token-Speicherung in verschlüsselten Dateien
- Scoped API Permissions (nur Calendar-Zugriff)
- Service Account für Google API (kein User-Consent)
- HMAC-SHA512 für Advoware Token-Generierung
- Token-Caching in Redis mit TTL
- MD5-Token für Sync-Validierung mit Salt
- Scoped Permissions (nur Calendar-Zugriff)
- Audit-Logs für alle Änderungen
## Bekannte Probleme und Workarounds
### Advoware API
- **Parameter-Typen:** Alle Query-Parameter müssen Strings sein (z.B. `'true'` statt `True`)
- **Response-Formate:** Manchmal HTML statt JSON, auch bei 200 Status
- **Content-Type:** Nicht immer korrekt gesetzt, führt zu Parse-Fehlern
- **Zeitformate:** Inkonsistente Formate, manuelle Parsing erforderlich
- **Rate Limits:** Keine dokumentierten Limits, aber praktische Limits vorhanden
### Google Calendar API
- **Rate Limits:** 403/429 mit Backoff-Handling
- **ACL-Sharing:** Owner-Rolle für Hauptaccount erforderlich
- **Event-Updates:** Vollständige Event-Daten bei Updates senden
### Sync-Logik
- **Token-Mismatch:** Verhindert unbefugte Änderungen
- **Deleted Tracking:** Verhindert Re-Sync gelöschter Termine
- **Änderungsvergleich:** Nur tatsächliche Änderungen syncen
## Erweiterungen
### Geplante Features
- Inkrementelle Syncs (nur geänderte Termine)
- Inkrementelle Syncs (nur geänderte Termine seit letztem Sync)
- Konfliktlösungsstrategien (Advoware gewinnt, Google gewinnt, Manuell)
- Batch-Verarbeitung für Performance
- Batch-Verarbeitung für bessere Performance
- Webhook-Integration für Echtzeit-Syncs
- Mehrere Google-Accounts unterstützen
- Outlook/Apple Calendar Integration
### Integration mit anderen Systemen
- Outlook Calendar
- Apple Calendar
- Mobile Apps
- Notification-Systeme
### Code-Verbesserungen
- Unit-Tests für API-Calls
- Mock-Server für Testing
- Config-Validation beim Startup
- Health-Checks für beide APIs
- Metrics-Export (Prometheus)