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
frNrwerden als neue Termine in Advoware erstellt - Die generierte
frNrwird 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
frNrum Re-Sync zu verhindern
API-Endpunkte
Advoware API
GET /api/v1/advonet/Mitarbeiter?aktiv=true- Liste aktiver MitarbeiterGET /api/v1/advonet/Termine?frnr={frnr}- Einzelner TerminGET /api/v1/advonet/Termine?kuerzel={kuerzel}&from={date}&to={date}- Termine eines MitarbeitersPOST /api/v1/advonet/Termine- Neuen Termin erstellenPUT /api/v1/advonet/Termine- Termin aktualisierenDELETE /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', nichtTrue) - 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:
datumalsYYYY-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:
{
"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:
{
"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
- Google Cloud Console Projekt erstellen
- Google Calendar API aktivieren
- Service Account erstellen (kein OAuth)
service-account.jsonDatei im Projektverzeichnis bereitstellen
Advoware API Credentials
OAuth-ähnliche Authentifizierung mit HMAC-Signature.
Umgebungsvariablen
# 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
curl -X POST "http://localhost:3000/advoware/calendar/sync" \
-H "Content-Type: application/json" \
-d '{"full_content": true}'
Event-basierter Sync
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
{
"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
{
"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'stattTrue) - 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)