Files
motia/bitbylaw/scripts/test_espocrm_kommunikation.py
bitbylaw ebbbf419ee feat: Implement bidirectional synchronization utilities for Advoware and EspoCRM communications
- Added KommunikationSyncManager class to handle synchronization logic.
- Implemented methods for loading data, computing diffs, and applying changes between Advoware and EspoCRM.
- Introduced 3-way diffing mechanism to intelligently resolve conflicts.
- Added helper methods for creating empty slots and detecting changes in communications.
- Enhanced logging for better traceability during synchronization processes.
2026-02-08 19:53:40 +00:00

278 lines
9.3 KiB
Python

"""
Test: EspoCRM Kommunikation - Wie werden Kontaktdaten gespeichert?
Prüfe:
1. Gibt es ein separates CKommunikation Entity?
2. Wie sind Telefon/Email/Fax in CBeteiligte gespeichert?
3. Sind es Arrays oder einzelne Felder?
"""
import asyncio
import json
from services.espocrm import EspoCRMAPI
# Test-Beteiligter mit Kommunikationsdaten
TEST_BETEILIGTE_ID = '68e4af00172be7924' # Angela Mustermanns
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): print(f"[DEBUG] {msg}")
def __init__(self):
self.logger = self.Logger()
def print_section(title):
print("\n" + "="*70)
print(title)
print("="*70)
async def test_cbeteiligte_structure():
"""Analysiere CBeteiligte Kommunikationsfelder"""
print_section("TEST 1: CBeteiligte Entity Struktur")
context = SimpleContext()
espo = EspoCRMAPI(context)
# Hole Beteiligten
entity = await espo.get_entity('CBeteiligte', TEST_BETEILIGTE_ID)
print(f"\n✅ Beteiligter geladen: {entity.get('name')}")
print(f" ID: {entity.get('id')}")
print(f" betNr: {entity.get('betnr')}")
# Suche nach Kommunikationsfeldern
print("\n📊 Kommunikations-relevante Felder:")
comm_fields = [
'phoneNumber', 'phoneNumberData',
'emailAddress', 'emailAddressData',
'fax', 'faxData',
'mobile', 'mobileData',
'website',
# Plural Varianten
'phoneNumbers', 'emailAddresses', 'faxNumbers',
# Link-Felder
'kommunikationIds', 'kommunikationNames',
'kommunikationenIds', 'kommunikationenNames',
'ckommunikationIds', 'ckommunikationNames'
]
found_fields = {}
for field in comm_fields:
if field in entity:
value = entity[field]
found_fields[field] = value
print(f"\n{field}:")
print(f" Typ: {type(value).__name__}")
if isinstance(value, list):
print(f" Anzahl: {len(value)}")
if len(value) > 0:
print(f" Beispiel: {json.dumps(value[0], indent=6, ensure_ascii=False)}")
elif isinstance(value, dict):
print(f" Keys: {list(value.keys())}")
print(f" Content: {json.dumps(value, indent=6, ensure_ascii=False)}")
else:
print(f" Wert: {value}")
if not found_fields:
print("\n ⚠️ Keine Standard-Kommunikationsfelder gefunden")
# Zeige alle Felder die "comm", "phone", "email", "fax", "tel" enthalten
print("\n📋 Alle Felder mit Kommunikations-Keywords:")
keywords = ['comm', 'phone', 'email', 'fax', 'tel', 'mobil', 'kontakt']
matching_fields = {}
for key, value in entity.items():
key_lower = key.lower()
if any(kw in key_lower for kw in keywords):
matching_fields[key] = value
print(f"{key}: {type(value).__name__}")
if isinstance(value, (str, int, bool)) and value:
print(f" = {value}")
return entity, found_fields
async def test_ckommunikation_entity():
"""Prüfe ob CKommunikation Entity existiert"""
print_section("TEST 2: CKommunikation Entity")
context = SimpleContext()
espo = EspoCRMAPI(context)
# Versuche CKommunikation zu listen
try:
result = await espo.list_entities('CKommunikation', max_size=5)
print(f"✅ CKommunikation Entity existiert!")
print(f" Anzahl gefunden: {len(result)}")
if result:
print(f"\n📋 Beispiel-Kommunikation:")
print(json.dumps(result[0], indent=2, ensure_ascii=False))
return True, result
except Exception as e:
if '404' in str(e) or 'not found' in str(e).lower():
print(f"❌ CKommunikation Entity existiert NICHT")
print(f" Fehler: {e}")
return False, None
else:
print(f"⚠️ Fehler beim Abrufen: {e}")
return None, None
async def test_entity_metadata():
"""Hole Entity-Metadaten von CBeteiligte"""
print_section("TEST 3: CBeteiligte Metadaten")
context = SimpleContext()
espo = EspoCRMAPI(context)
# Hole Metadaten (falls API das unterstützt)
try:
# Versuche Entity-Defs zu holen
metadata = await espo.api_call('/Metadata', method='GET')
if 'entityDefs' in metadata and 'CBeteiligte' in metadata['entityDefs']:
beteiligte_def = metadata['entityDefs']['CBeteiligte']
print("✅ Metadaten verfügbar")
if 'fields' in beteiligte_def:
fields = beteiligte_def['fields']
print(f"\n📊 Kommunikations-Felder in Definition:")
for field_name, field_def in fields.items():
field_lower = field_name.lower()
if any(kw in field_lower for kw in ['comm', 'phone', 'email', 'fax', 'tel']):
print(f"\n{field_name}:")
print(f" type: {field_def.get('type')}")
if 'entity' in field_def:
print(f" entity: {field_def.get('entity')}")
if 'link' in field_def:
print(f" link: {field_def.get('link')}")
return metadata
except Exception as e:
print(f"⚠️ Metadaten nicht verfügbar: {e}")
return None
async def test_list_all_entities():
"""Liste alle verfügbaren Entities"""
print_section("TEST 4: Alle verfügbaren Entities")
context = SimpleContext()
espo = EspoCRMAPI(context)
# Häufige Entity-Namen die mit Kommunikation zu tun haben könnten
test_entities = [
'CKommunikation',
'Kommunikation',
'Communication',
'PhoneNumber',
'EmailAddress',
'CPhoneNumber',
'CEmailAddress',
'CPhone',
'CEmail',
'CContact',
'ContactData'
]
print("\n🔍 Teste verschiedene Entity-Namen:\n")
existing = []
for entity_name in test_entities:
try:
result = await espo.list_entities(entity_name, max_size=1)
print(f"{entity_name} - existiert ({len(result)} gefunden)")
existing.append(entity_name)
except Exception as e:
if '404' in str(e) or 'not found' in str(e).lower():
print(f"{entity_name} - existiert nicht")
else:
print(f" ⚠️ {entity_name} - Fehler: {str(e)[:50]}")
return existing
async def main():
print("\n" + "="*70)
print("ESPOCRM KOMMUNIKATION ANALYSE")
print("="*70)
print("\nZiel: Verstehen wie Kommunikationsdaten in EspoCRM gespeichert sind")
print("Frage: Gibt es separate Kommunikations-Entities oder nur Felder?\n")
try:
# Test 1: CBeteiligte Struktur
entity, comm_fields = await test_cbeteiligte_structure()
# Test 2: CKommunikation Entity
ckommunikation_exists, ckommunikation_data = await test_ckommunikation_entity()
# Test 3: Metadaten
# metadata = await test_entity_metadata()
# Test 4: Liste entities
existing_entities = await test_list_all_entities()
# Zusammenfassung
print_section("ZUSAMMENFASSUNG")
print("\n📊 Erkenntnisse:")
if comm_fields:
print(f"\n✅ CBeteiligte hat Kommunikationsfelder:")
for field, value in comm_fields.items():
vtype = type(value).__name__
print(f"{field} ({vtype})")
if ckommunikation_exists:
print(f"\n✅ CKommunikation Entity existiert")
print(f" → Separate Kommunikations-Entities möglich")
elif ckommunikation_exists == False:
print(f"\n❌ CKommunikation Entity existiert NICHT")
print(f" → Kommunikation nur als Felder in CBeteiligte")
if existing_entities:
print(f"\n📋 Gefundene Kommunikations-Entities:")
for ename in existing_entities:
print(f"{ename}")
print("\n💡 Empfehlung:")
if not comm_fields and not ckommunikation_exists:
print(" ⚠️ Keine Kommunikationsstruktur gefunden")
print(" → Eventuell müssen Custom Fields erst angelegt werden")
elif comm_fields and not ckommunikation_exists:
print(" → Verwende vorhandene Felder in CBeteiligte (phoneNumber, emailAddress, etc.)")
print(" → Sync als Teil des Beteiligte-Syncs (nicht separat)")
elif ckommunikation_exists:
print(" → Verwende CKommunikation Entity für separaten Kommunikations-Sync")
print(" → Ermöglicht mehrere Kommunikationseinträge pro Beteiligten")
except Exception as e:
print(f"\n❌ Fehler: {e}")
import traceback
traceback.print_exc()
if __name__ == '__main__':
asyncio.run(main())