- parse_times erkennt jetzt recurring Events (dauertermin=1 + turnus/turnusArt > 0) - Für recurring Events wird das Ende aus dem gleichen Tag wie Start berechnet - datumBis wird nur noch für die RRULE-Serie verwendet, nicht für jeden Termin - Fix für Termin 84389: Statt 15-Tage-Terminen jetzt korrekte 30-Minuten-Termine
Motia Advoware-EspoCRM Integration
Dieses Projekt implementiert eine robuste Integration zwischen Advoware und EspoCRM über das Motia-Framework. Es bietet eine vollständige API-Proxy für Advoware und Webhook-Handler für EspoCRM, um Änderungen an Beteiligte-Entitäten zu synchronisieren.
Übersicht
Das System besteht aus drei Hauptkomponenten:
- Advoware API Proxy: Vollständige REST-API-Proxy für alle HTTP-Methoden (GET, POST, PUT, DELETE)
- EspoCRM Webhook Receiver: Empfängt Webhooks für CRUD-Operationen auf Beteiligte-Entitäten
- Event-Driven Sync: Verarbeitet Synchronisationsereignisse mit Redis-basierter Deduplikation
Architektur
Komponenten
- Motia Framework: Event-driven Backend-Orchestrierung
- Python Steps: Asynchrone Verarbeitung mit aiohttp und redis-py
- Advoware API Client: Authentifizierte API-Kommunikation mit Token-Management
- Redis: Deduplikation von Webhook-Events und Caching
- EspoCRM Integration: Webhook-Handler für create/update/delete Operationen
Datenfluss
EspoCRM Webhook → VMH Webhook Receiver → Redis Deduplication → Event Emission → Sync Handler
Advoware API → Proxy Steps → Response
Setup
Voraussetzungen
- Python 3.13+
- Node.js 18+
- Redis Server
- Motia CLI
Installation
-
Repository klonen und Dependencies installieren:
cd /opt/motia-app/bitbylaw npm install pip install -r requirements.txt -
Umgebungsvariablen konfigurieren: Erstellen Sie eine
.env-Datei mit folgenden Variablen:ADVOWARE_BASE_URL=https://api.advoware.com ADVOWARE_USERNAME=your_username ADVOWARE_PASSWORD=your_password REDIS_URL=redis://localhost:6379 ESPOCRM_WEBHOOK_SECRET=your_webhook_secret -
Redis starten:
redis-server -
Motia starten:
motia start
Verwendung
Advoware API Proxy
Die Proxy-Endpunkte spiegeln die Advoware-API wider:
GET /api/advoware/*- Daten abrufenPOST /api/advoware/*- Neue Ressourcen erstellenPUT /api/advoware/*- Ressourcen aktualisierenDELETE /api/advoware/*- Ressourcen löschen
Beispiel:
curl -X GET "http://localhost:3000/api/advoware/employees"
Für detaillierte Informationen zu den Proxy-Steps siehe steps/advoware_proxy/README.md.
EspoCRM Webhooks
Webhooks werden automatisch von EspoCRM gesendet für Änderungen an Beteiligte-Entitäten:
- Create:
/webhooks/vmh/beteiligte/create - Update:
/webhooks/vmh/beteiligte/update - Delete:
/webhooks/vmh/beteiligte/delete
Für detaillierte Informationen zu den Webhook- und Sync-Steps siehe steps/vmh/README.md.
Synchronisation
Die Synchronisation läuft event-driven ab:
- Webhook-Events werden in Redis-Queues dedupliziert
- Events werden an den Sync-Handler emittiert
- Sync-Handler verarbeitet die Änderungen (aktuell Placeholder)
Konfiguration
Motia Workbench
Die Flows sind in motia-workbench.json definiert:
advoware-proxy: API-Proxy-Flowsvmh-webhook: Webhook-Receiver-Flowsbeteiligte-sync: Synchronisations-Flow
Redis Keys
vmh:webhook:create: Create-Event Queuevmh:webhook:update: Update-Event Queuevmh:webhook:delete: Delete-Event Queue
Entwicklung
Projektstruktur
bitbylaw/
├── steps/
│ ├── advoware_proxy/ # API Proxy Steps - siehe [README](steps/advoware_proxy/README.md)
│ │ ├── advoware_api_proxy_get_step.py
│ │ ├── advoware_api_proxy_post_step.py
│ │ ├── advoware_api_proxy_put_step.py
│ │ └── advoware_api_proxy_delete_step.py
│ └── vmh/ # VMH Webhook & Sync Steps - siehe [README](steps/vmh/README.md)
│ ├── webhook/ # Webhook Receiver Steps
│ │ ├── beteiligte_create_api_step.py
│ │ ├── beteiligte_update_api_step.py
│ │ └── beteiligte_delete_api_step.py
│ └── beteiligte_sync_event_step.py # Sync Handler
├── services/
│ └── advoware.py # API Client
├── config.py # Configuration
├── motia-workbench.json # Flow Definitions
├── package.json
├── requirements.txt
└── tsconfig.json
Testing
API Proxy testen:
curl -X GET "http://localhost:3000/api/advoware/employees"
Webhook simulieren:
curl -X POST "http://localhost:3000/webhooks/vmh/beteiligte/create" \
-H "Content-Type: application/json" \
-d '{"id": "123", "name": "Test Beteiligte"}'
Logging
Alle Steps enthalten detaillierte Logging-Ausgaben für Debugging:
- API-Requests/Responses
- Redis-Operationen
- Event-Emission
- Fehlerbehandlung
Deployment
Docker
FROM python:3.13-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
EXPOSE 3000
CMD ["motia", "start"]
Production Setup
- Redis Cluster für Hochverfügbarkeit
- Load Balancer für API-Endpunkte
- Monitoring für Sync-Operationen
- Backup-Strategie für Redis-Daten
Fehlerbehebung
Häufige Probleme
- Context Attribute Error: Verwenden Sie
Configstattcontext.config - Redis Connection Failed: Überprüfen Sie Redis-URL und Netzwerkverbindung
- Webhook Duplikate: Redis-Deduplikation verhindert Mehrfachverarbeitung
Logs überprüfen
motia logs
Calendar Sync
Das System enthält auch eine bidirektionale Kalender-Synchronisation zwischen Advoware und Google Calendar.
Architektur
- PostgreSQL Hub: Speichert Sync-Zustand und verhindert Datenverlust
- Event-Driven Sync: 4-Phasen-Sync (Neu, Gelöscht, Aktualisiert)
- Safe Wrappers: Globale Write-Protection für Advoware-Schreiboperationen
- Rate Limiting: Backoff-Handling für Google Calendar API-Limits
Dauertermine (Recurring Appointments)
Advoware verwendet dauertermin=1 für wiederkehrende Termine mit folgenden Feldern:
turnus: Intervall (z.B. 1 = jeden, 3 = jeden 3.)turnusArt: Frequenz-Einheit1= Täglich (DAILY)2= Wöchentlich (WEEKLY)3= Monatlich (MONTHLY)4= Jährlich (YEARLY)
datumBis: Enddatum der Wiederholung
RRULE-Generierung:
RRULE:FREQ={FREQ};INTERVAL={turnus};UNTIL={datumBis}
Beispiel: turnus=3, turnusArt=1 → RRULE:FREQ=DAILY;INTERVAL=3;UNTIL=20251224
Setup
- Google Service Account:
service-account.jsonim Projektroot - Umgebungsvariablen:
ADVOWARE_WRITE_PROTECTION=false # Global write protection POSTGRES_HOST=localhost GOOGLE_CALENDAR_SERVICE_ACCOUNT_PATH=service-account.json - Trigger Sync:
curl -X POST "http://localhost:3000/advoware/calendar/sync" -H "Content-Type: application/json" -d '{"full_content": true}'
Rate Limiting & Backoff
- Google Calendar API: 403-Fehler bei Rate-Limits werden mit exponentiellem Backoff (max. 60s) wiederholt
- Delays: 100ms zwischen API-Calls zur Vermeidung von Limits
- Retry-Logic: Max. 4 Versuche mit base=4
Sicherheit
- Write Protection:
ADVOWARE_WRITE_PROTECTION=truedeaktiviert alle Advoware-Schreiboperationen - Per-User Calendars: Automatische Erstellung und Freigabe von Google-Calendars pro Mitarbeiter
Troubleshooting
- Rate Limit Errors: Logs zeigen Backoff-Retries; warten oder Limits erhöhen
- Sync Failures:
ADVOWARE_WRITE_PROTECTION=falsesetzen für Debugging - Calendar Access: Service Account muss Owner-Rechte haben
Lizenz
[License Information]
Beitrag
Bitte erstellen Sie Issues für Bugs oder Feature-Requests. Pull-Requests sind willkommen!