- 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.
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:
gueltigBisist 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
NotificationManagerKlasse - 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ötigaddress_reactivate_required- Neue Adresse erstellenaddress_field_update_required- READ-ONLY Felder ändernreadonly_field_conflict- Sync-Konfliktmissing_in_advoware- Element fehltgeneral_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/):
-
test_adressen_api.py- Haupttest (7 Tests)- POST/PUT mit allen Feldern
- Feld-für-Feld Verifikation
- Response-Analyse
-
test_adressen_delete_matching.py- DELETE + Matching- DELETE-Funktionalität (→ 403)
bemerkung-basiertes Matching- Stabilität von
bemerkungbei PUT
-
test_adressen_deactivate_ordering.py- DeaktivierunggueltigBisnachträglich setzen (→ READ-ONLY)reihenfolgeIndexVerhalten- Automatisches Ans-Ende-Reihen
-
test_adressen_gueltigbis_modify.py- Soft-DeletegueltigBisändern (→ nicht möglich)- Verschiedene Methoden getestet
-
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
- Felder vorhanden:
- Notification-System testen
- Task-Erstellung funktioniert
- Assigned Users werden benachrichtigt
Phase 2: Mapper ⏳
services/adressen_mapper.pyerstellenclass 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.pyerstellenclass 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
- Hauptdokumentation:
docs/ADRESSEN_SYNC_ANALYSE.md - Notification-Utility:
services/notification_utils.py - Test-Scripts:
scripts/test_adressen_*.py - Swagger-Doku: Advoware API v1 - Adressen Endpoints
Erstellt: 8. Februar 2026
Autor: GitHub Copilot
Review: Pending