""" TEST: Können wir eigene IDs in emailAddressData setzen? Wenn EspoCRM IDs beim UPDATE akzeptiert und speichert, dann können wir: - Advoware-ID als 'id' in emailAddressData speichern - Stabiles Matching haben - Bidirektionalen Sync machen Vorsichtiger Test mit Backup! """ import asyncio import json from services.espocrm import EspoCRMAPI TEST_BETEILIGTE_ID = '68e4af00172be7924' class SimpleContext: class Logger: def info(self, msg): print(f"[INFO] {msg}") def error(self, msg): print(f"[ERROR] {msg}") def warning(self, msg): print(f"[WARN] {msg}") def debug(self, msg): pass def __init__(self): self.logger = self.Logger() def print_section(title): print("\n" + "="*70) print(title) print("="*70) async def test_id_persistence(): """ Teste ob EspoCRM IDs in emailAddressData speichert Ablauf: 1. Hole aktuelle Daten (Backup) 2. Füge 'id' Feld zu EINEM Email hinzu 3. UPDATE 4. GET wieder 5. Prüfe ob 'id' noch da ist 6. Restore original falls nötig """ print_section("TEST: ID Persistence in emailAddressData") context = SimpleContext() espo = EspoCRMAPI(context) # 1. Backup print("\n1️⃣ Backup: Hole aktuelle Daten") entity_backup = await espo.get_entity('CBeteiligte', TEST_BETEILIGTE_ID) emails_backup = entity_backup.get('emailAddressData', []) print(f" Backup: {len(emails_backup)} Emails gesichert") for email in emails_backup: print(f" • {email['emailAddress']}") # 2. Modifiziere NUR das erste Email (primary) print("\n2️⃣ Modifikation: Füge 'id' zu primary Email hinzu") emails_modified = [] for i, email in enumerate(emails_backup): email_copy = email.copy() if email_copy.get('primary'): # Nur primary modifizieren # Nutze einen recognizable Test-Wert test_id = f"advoware-{i+1}-test-123" email_copy['id'] = test_id print(f" ✏️ {email['emailAddress']:40s} → id={test_id}") else: print(f" ⏭️ {email['emailAddress']:40s} (unverändert)") emails_modified.append(email_copy) # 3. UPDATE print("\n3️⃣ UPDATE: Sende modifizierte Daten") try: await espo.update_entity('CBeteiligte', TEST_BETEILIGTE_ID, { 'emailAddressData': emails_modified }) print(" ✅ UPDATE erfolgreich") except Exception as e: print(f" ❌ UPDATE fehlgeschlagen: {e}") return # 4. GET wieder print("\n4️⃣ GET: Hole Daten wieder ab") await asyncio.sleep(0.5) # Kurze Pause entity_after = await espo.get_entity('CBeteiligte', TEST_BETEILIGTE_ID) emails_after = entity_after.get('emailAddressData', []) print(f" Nach UPDATE: {len(emails_after)} Emails") # 5. Vergleiche print("\n5️⃣ VERGLEICH: Ist 'id' noch da?") id_found = False for email in emails_after: email_addr = email['emailAddress'] has_id = 'id' in email if has_id: print(f" ✅ {email_addr:40s} → id={email['id']}") id_found = True else: print(f" ❌ {email_addr:40s} → KEIN id Feld") # 6. Ergebnis print(f"\n6️⃣ ERGEBNIS:") if id_found: print(" 🎉 SUCCESS! EspoCRM speichert und liefert 'id' Feld zurück!") print(" → Wir können Advoware-IDs in emailAddressData speichern") print(" → Stabiles bidirektionales Matching möglich") else: print(" ❌ FAILED: EspoCRM ignoriert/entfernt 'id' Feld") print(" → Wert-basiertes Matching notwendig") print(" → Hybrid-Strategie (primary-Flag) ist beste Option") # 7. Restore (optional - nur wenn User will) print(f"\n7️⃣ CLEANUP:") print(" Original-Daten (ohne id):") for email in emails_backup: print(f" • {email['emailAddress']}") if id_found: restore = input("\n 🔄 Restore zu Original (ohne id)? [y/N]: ").strip().lower() if restore == 'y': await espo.update_entity('CBeteiligte', TEST_BETEILIGTE_ID, { 'emailAddressData': emails_backup }) print(" ✅ Restored") else: print(" ⏭️ Nicht restored (id bleibt)") return id_found async def test_custom_field_approach(): """ Alternative: Nutze ein custom field in CBeteiligte für ID-Mapping Idee: Speichere JSON-Mapping in einem Textfeld """ print_section("ALTERNATIVE: Custom Field für ID-Mapping") print("\n💡 Idee: Nutze custom field 'kommunikationMapping'") print(" Struktur:") print(" {") print(' "emails": [') print(' {"emailAddress": "max@example.com", "advowareId": 123, "advowareRowId": "ABC"}') print(' ],') print(' "phones": [') print(' {"phoneNumber": "+49...", "advowareId": 456, "advowareRowId": "DEF"}') print(' ]') print(" }") print("\n✅ Vorteile:") print(" • Stabiles Matching via advowareId") print(" • Change Detection via advowareRowId") print(" • Bidirektionaler Sync möglich") print("\n❌ Nachteile:") print(" • Erfordert custom field in EspoCRM") print(" • Daten-Duplikation (in Data + Mapping)") print(" • Fragil wenn emailAddress/phoneNumber ändert") context = SimpleContext() espo = EspoCRMAPI(context) # Prüfe ob custom field existiert print("\n🔍 Prüfe ob 'kommunikationMapping' Feld existiert:") try: entity = await espo.get_entity('CBeteiligte', TEST_BETEILIGTE_ID) if 'kommunikationMapping' in entity: print(f" ✅ Feld existiert: {entity['kommunikationMapping']}") else: print(f" ❌ Feld existiert nicht") print(f" → Müsste in EspoCRM angelegt werden") except Exception as e: print(f" ❌ Error: {e}") async def main(): print("\n" + "="*70) print("TEST: KÖNNEN WIR EIGENE IDs IN emailAddressData SETZEN?") print("="*70) print("\nZiel: Herausfinden ob EspoCRM 'id' Felder akzeptiert und speichert\n") try: # Haupttest id_works = await test_id_persistence() # Alternative await test_custom_field_approach() print_section("FINAL RECOMMENDATION") if id_works: print("\n🎯 EMPFEHLUNG: Nutze 'id' Feld in emailAddressData") print("\n📋 Implementation:") print(" 1. Bei Advoware → EspoCRM: Füge 'id' mit Advoware-ID hinzu") print(" 2. Matching via 'id' Feld") print(" 3. Change Detection via Advoware rowId") print(" 4. Bidirektionaler Sync möglich") else: print("\n🎯 EMPFEHLUNG A: Hybrid-Strategie (primary-Flag)") print(" • Einfach zu implementieren") print(" • Nutzt Standard-EspoCRM") print(" • Eingeschränkt bidirektional") print("\n🎯 EMPFEHLUNG B: Custom Field 'kommunikationMapping'") print(" • Vollständig bidirektional") print(" • Erfordert EspoCRM-Anpassung") print(" • Komplexere Implementation") except Exception as e: print(f"\n❌ Fehler: {e}") import traceback traceback.print_exc() if __name__ == "__main__": asyncio.run(main())