Files
motia/bitbylaw/docs/ADRESSEN_SYNC_SUMMARY.md
bitbylaw c770f2c8ee feat: Implement address synchronization between EspoCRM and Advoware
- Add AdressenMapper for transforming addresses between EspoCRM and Advoware formats.
- Create AdressenSync class to handle address creation, update, and deletion synchronization.
- Introduce NotificationManager for managing manual intervention notifications in case of sync issues.
- Implement detailed logging for address sync operations and error handling.
- Ensure READ-ONLY field changes are detected and notified for manual resolution.
2026-02-08 14:29:29 +00:00

7.6 KiB

Adressen-Sync: Zusammenfassung & Implementierungsplan

Datum: 8. Februar 2026
Status: Analyse abgeschlossen, bereit für Implementierung


📋 Executive Summary

Was funktioniert:

  • CREATE (POST): Alle Felder können gesetzt werden
  • UPDATE (PUT): 4 Haupt-Adressfelder (strasse, plz, ort, anschrift)
  • MATCHING: Via bemerkung-Feld mit EspoCRM-ID (stabil, READ-ONLY)
  • SYNC from Advoware: Vollständig möglich

Was nicht funktioniert:

  • DELETE: 403 Forbidden (nicht verfügbar)
  • Soft-Delete: gueltigBis ist READ-ONLY (kann nicht nachträglich gesetzt werden)
  • 8 Felder READ-ONLY bei PUT: land, postfach, postfachPLZ, standardAnschrift, bemerkung, gueltigVon, gueltigBis, reihenfolgeIndex

💡 Lösung: Hybrid-Ansatz

Automatischer Sync + Notification-System für manuelle Eingriffe


🏗️ Implementierte Komponenten

1. Notification-System

Datei: services/notification_utils.py

Features:

  • Zentrale NotificationManager Klasse
  • Task-Erstellung in EspoCRM mit Schritt-für-Schritt Anleitung
  • In-App Notifications an assigned Users
  • 6 vordefinierte Action-Types:
    • address_delete_required - DELETE manuell nötig
    • address_reactivate_required - Neue Adresse erstellen
    • address_field_update_required - READ-ONLY Felder ändern
    • readonly_field_conflict - Sync-Konflikt
    • missing_in_advoware - Element fehlt
    • general_manual_action - Allgemein

Verwendung:

from services.notification_utils import NotificationManager

notif_mgr = NotificationManager(espocrm_api, context)

# DELETE erforderlich
await notif_mgr.notify_manual_action_required(
    entity_type='CAdressen',
    entity_id='65abc123',
    action_type='address_delete_required',
    details={
        'betnr': '104860',
        'strasse': 'Teststraße 123',
        'plz': '30159',
        'ort': 'Hannover'
    }
)
# → Erstellt Task + Notification mit detaillierter Anleitung

2. Umfassende Test-Suite

Test-Scripts (alle in scripts/):

  1. test_adressen_api.py - Haupttest (7 Tests)

    • POST/PUT mit allen Feldern
    • Feld-für-Feld Verifikation
    • Response-Analyse
  2. test_adressen_delete_matching.py - DELETE + Matching

    • DELETE-Funktionalität (→ 403)
    • bemerkung-basiertes Matching
    • Stabilität von bemerkung bei PUT
  3. test_adressen_deactivate_ordering.py - Deaktivierung

    • gueltigBis nachträglich setzen (→ READ-ONLY)
    • reihenfolgeIndex Verhalten
    • Automatisches Ans-Ende-Reihen
  4. test_adressen_gueltigbis_modify.py - Soft-Delete

    • gueltigBis ändern (→ nicht möglich)
    • Verschiedene Methoden getestet
  5. test_put_response_detail.py - PUT-Analyse

    • Welche Felder werden wirklich geändert
    • Response vs. GET Vergleich

3. Dokumentation

Datei: docs/ADRESSEN_SYNC_ANALYSE.md

Inhalte:

  • Swagger API-Dokumentation
  • EspoCRM Entity-Struktur
  • Detaillierte Test-Ergebnisse
  • Sync-Strategien (3 Optionen evaluiert)
  • Finale Empfehlung: Hybrid-Ansatz
  • Feld-Mappings
  • Risiko-Analyse
  • Implementierungsplan

🔑 Kritische Erkenntnisse

ID-Mapping

❌ id = 0          → Immer 0, unbrauchbar
✅ bemerkung       → Stabil (READ-ONLY), perfekt für Matching
✅ reihenfolgeIndex → Stabil, automatisch vergeben, für PUT-Endpoint
❌ rowId           → Ändert sich bei PUT, nicht für Matching!

PUT-Feldübersicht

Feld POST PUT Matching
strasse -
plz -
ort -
land READ-ONLY -
postfach READ-ONLY -
postfachPLZ READ-ONLY -
anschrift -
standardAnschrift READ-ONLY -
bemerkung READ-ONLY Perfekt!
gueltigVon READ-ONLY -
gueltigBis READ-ONLY -
reihenfolgeIndex - System Für PUT

🚀 Nächste Schritte

Phase 1: Validierung

  • EspoCRM CAdressen Entity prüfen
    • Felder vorhanden: advowareIndexId, advowareRowId, syncStatus, isActive, manualActionNote
    • Relation zu CBeteiligte korrekt
  • Notification-System testen
    • Task-Erstellung funktioniert
    • Assigned Users werden benachrichtigt

Phase 2: Mapper

  • services/adressen_mapper.py erstellen
    class AdressenMapper:
        def map_espocrm_to_advoware(espo_addr) -> dict
        def map_advoware_to_espocrm(advo_addr) -> dict
        def find_by_bemerkung(addresses, espo_id) -> dict
        def detect_readonly_changes(espo, advo) -> dict
    

Phase 3: Sync-Service

  • services/adressen_sync.py erstellen
    class AdressenSyncService:
        async def create_address(espo_addr)
        async def update_address(espo_addr)
        async def delete_address(espo_addr)  # → Notification
        async def sync_from_advoware(betnr, espo_beteiligte_id)
    

Phase 4: Integration

  • In bestehenden Beteiligte-Sync integrieren oder
  • Eigener Adressen-Sync Step

Phase 5: Testing

  • Unit Tests für Mapper
  • Integration Tests mit Test-Daten
  • End-to-End Test: CREATE → UPDATE → DELETE
  • Notification-Flow testen

Phase 6: Deployment

  • Staging-Test mit echten Daten
  • User-Schulung: Manuelle Eingriffe
  • Monitoring einrichten
  • Production Rollout

📝 Wichtige Hinweise für Entwickler

Matching-Strategie

IMMER via bemerkung-Feld:

# Beim CREATE:
bemerkung = f"EspoCRM-ID: {espocrm_address_id}"

# Beim Sync:
espocrm_id = parse_espocrm_id_from_bemerkung(advo_addr['bemerkung'])
# Robust gegen User-Änderungen:
import re
match = re.search(r'EspoCRM-ID:\s*([a-f0-9-]+)', bemerkung)
espocrm_id = match.group(1) if match else None

Notification Trigger

Immer Notifications erstellen bei:

  • DELETE-Request (API nicht verfügbar)
  • PUT mit READ-ONLY Feldern (land, postfach, etc.)
  • Reaktivierung (neue Adresse erstellen)
  • Adresse direkt in Advoware erstellt (fehlende bemerkung)

Sync-Richtung

  • EspoCRM → Advoware: Für CREATE/UPDATE
  • Advoware → EspoCRM: Master für "Existenz"
  • Konflikt-Resolution: Siehe Dokumentation

Aktuelle Adresse-Matching

Wichtig: Die "aktuelle" Adresse muss in beiden Systemen gleich sein!

Strategie:

# In Advoware: standardAnschrift = true (READ-ONLY!)
# In EspoCRM: isPrimary = true (eigenes Feld)

# Sync-Logik:
if espo_addr['isPrimary']:
    # Prüfe ob Advoware-Adresse standardAnschrift = true hat
    if not advo_addr['standardAnschrift']:
        # → Notification: Hauptadresse manuell in Advoware setzen
        await notify_main_address_mismatch(...)

📊 Metriken & Monitoring

Zu überwachende KPIs:

  • Anzahl erstellter Notifications pro Tag
  • Durchschnittliche Zeit bis Task-Completion
  • Anzahl gescheiterter Syncs
  • READ-ONLY Feld-Konflikte (Häufigkeit)
  • DELETE-Requests (manuell nötig)

Alerts einrichten für:

  • Mehr als 5 unerledigte DELETE-Tasks pro User
  • Sync-Fehlerrate > 10%
  • Tasks älter als 7 Tage

🔗 Referenzen


Erstellt: 8. Februar 2026
Autor: GitHub Copilot
Review: Pending