- Implemented comprehensive tests for the Kommunikation Sync functionality, covering base64 encoding, marker parsing, creation, type detection, and integration scenarios. - Added a verification script to check for unique IDs in Advoware communications, ensuring stability and integrity of the IDs. - Created utility scripts for code validation, notification testing, and PUT response detail analysis to enhance development and testing processes. - Updated README with details on new tools and their usage.
278 lines
9.3 KiB
Python
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())
|