Files
motia/bitbylaw
root 2bf37b8616 Fix: Korrekte Endzeiten für recurring Events
- 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
2025-10-24 19:48:12 +00:00
..
2025-10-19 14:57:07 +00:00
2025-10-19 14:57:07 +00:00

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:

  1. Advoware API Proxy: Vollständige REST-API-Proxy für alle HTTP-Methoden (GET, POST, PUT, DELETE)
  2. EspoCRM Webhook Receiver: Empfängt Webhooks für CRUD-Operationen auf Beteiligte-Entitäten
  3. 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

  1. Repository klonen und Dependencies installieren:

    cd /opt/motia-app/bitbylaw
    npm install
    pip install -r requirements.txt
    
  2. 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
    
  3. Redis starten:

    redis-server
    
  4. Motia starten:

    motia start
    

Verwendung

Advoware API Proxy

Die Proxy-Endpunkte spiegeln die Advoware-API wider:

  • GET /api/advoware/* - Daten abrufen
  • POST /api/advoware/* - Neue Ressourcen erstellen
  • PUT /api/advoware/* - Ressourcen aktualisieren
  • DELETE /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:

  1. Webhook-Events werden in Redis-Queues dedupliziert
  2. Events werden an den Sync-Handler emittiert
  3. Sync-Handler verarbeitet die Änderungen (aktuell Placeholder)

Konfiguration

Motia Workbench

Die Flows sind in motia-workbench.json definiert:

  • advoware-proxy: API-Proxy-Flows
  • vmh-webhook: Webhook-Receiver-Flows
  • beteiligte-sync: Synchronisations-Flow

Redis Keys

  • vmh:webhook:create: Create-Event Queue
  • vmh:webhook:update: Update-Event Queue
  • vmh: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

  1. Redis Cluster für Hochverfügbarkeit
  2. Load Balancer für API-Endpunkte
  3. Monitoring für Sync-Operationen
  4. Backup-Strategie für Redis-Daten

Fehlerbehebung

Häufige Probleme

  1. Context Attribute Error: Verwenden Sie Config statt context.config
  2. Redis Connection Failed: Überprüfen Sie Redis-URL und Netzwerkverbindung
  3. 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-Einheit
    • 1 = 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=1RRULE:FREQ=DAILY;INTERVAL=3;UNTIL=20251224

Setup

  1. Google Service Account: service-account.json im Projektroot
  2. Umgebungsvariablen:
    ADVOWARE_WRITE_PROTECTION=false  # Global write protection
    POSTGRES_HOST=localhost
    GOOGLE_CALENDAR_SERVICE_ACCOUNT_PATH=service-account.json
    
  3. 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=true deaktiviert 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=false setzen 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!