261 lines
8.2 KiB
Markdown
261 lines
8.2 KiB
Markdown
# Advoware Calendar Sync
|
|
|
|
Dieser Abschnitt implementiert die bidirektionale Synchronisation zwischen Advoware-Terminen und Google Calendar. Für jeden Mitarbeiter in Advoware wird automatisch ein entsprechender Google Calendar erstellt und gepflegt.
|
|
|
|
## Übersicht
|
|
|
|
Das System synchronisiert Termine zwischen:
|
|
- **Advoware**: Zentrale Terminverwaltung mit detaillierten Informationen
|
|
- **Google Calendar**: Benutzerfreundliche Kalenderansicht für jeden Mitarbeiter
|
|
|
|
## Funktionalität
|
|
|
|
### 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 mit Token-Validierung
|
|
|
|
#### Advoware → Google Calendar
|
|
- 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
|
|
|
|
### 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 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, ACL setzen)
|
|
- Event-Management (erstellen, aktualisieren, löschen)
|
|
- Service Account Authentifizierung mit Backoff bei Rate Limits
|
|
|
|
## Step-Konfiguration
|
|
|
|
### 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
|
|
- **Flows:** advoware
|
|
|
|
**Request Body:**
|
|
```json
|
|
{
|
|
"full_content": true // oder false für nur "blocked"
|
|
}
|
|
```
|
|
|
|
### 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. 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
|
|
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
|
|
|
|
### Manueller Sync
|
|
```bash
|
|
curl -X POST "http://localhost:3000/advoware/calendar/sync" \
|
|
-H "Content-Type: application/json" \
|
|
-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 Cron-Step führt täglich um 2:00 Uhr einen vollständigen Sync aus.
|
|
|
|
## Datenmapping
|
|
|
|
### Advoware → Google Calendar
|
|
```javascript
|
|
{
|
|
"summary": "Advoware blocked", // Immer "blocked" für Privacy
|
|
"description": `Advoware Termin ID: ${appointment.frNr}`,
|
|
"location": "",
|
|
"start": {
|
|
"dateTime": start_datetime, // Berechnet aus datum/uhrzeitVon
|
|
"timeZone": "Europe/Berlin"
|
|
},
|
|
"end": {
|
|
"dateTime": end_datetime, // Berechnet aus datumBis/uhrzeitBis
|
|
"timeZone": "Europe/Berlin"
|
|
},
|
|
"extendedProperties": {
|
|
"private": {
|
|
"advoware_frnr": appointment.frNr.toString()
|
|
}
|
|
}
|
|
}
|
|
```
|
|
|
|
### Google Calendar → Advoware
|
|
```javascript
|
|
{
|
|
"frNr": int(frnr),
|
|
"text": event.summary,
|
|
"notiz": updated_description, // Mit sync-info
|
|
"ort": event.location,
|
|
"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,
|
|
"vorbereitungsDauer": "00:00:00"
|
|
}
|
|
```
|
|
|
|
## Fehlerbehandlung
|
|
|
|
- **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 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 pro API
|
|
- Gelöschte Termine
|
|
- Token-Validierungsfehler
|
|
|
|
## Sicherheit
|
|
|
|
- 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 seit letztem Sync)
|
|
- Konfliktlösungsstrategien (Advoware gewinnt, Google gewinnt, Manuell)
|
|
- Batch-Verarbeitung für bessere Performance
|
|
- Webhook-Integration für Echtzeit-Syncs
|
|
- Mehrere Google-Accounts unterstützen
|
|
- Outlook/Apple Calendar Integration
|
|
|
|
### 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) |