- 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.
234 lines
8.0 KiB
Python
234 lines
8.0 KiB
Python
#!/usr/bin/env python3
|
||
"""
|
||
Vergleicht Advoware Entity (betNr 104860) mit EspoCRM Entity (68e3e7eab49f09adb)
|
||
um zu prüfen ob sie synchron sind.
|
||
"""
|
||
|
||
import asyncio
|
||
import sys
|
||
import json
|
||
from pathlib import Path
|
||
|
||
# Add parent directory to path
|
||
sys.path.insert(0, str(Path(__file__).parent.parent))
|
||
|
||
from services.advoware import AdvowareAPI
|
||
from services.advoware_service import AdvowareService
|
||
from services.espocrm import EspoCRMAPI
|
||
from services.espocrm_mapper import BeteiligteMapper
|
||
from services.beteiligte_sync_utils import BeteiligteSync
|
||
import hashlib
|
||
|
||
|
||
class SimpleContext:
|
||
"""Minimal context for logging"""
|
||
class Logger:
|
||
def info(self, msg): print(f"ℹ️ {msg}")
|
||
def debug(self, msg): print(f"🔍 {msg}")
|
||
def warn(self, msg): print(f"⚠️ {msg}")
|
||
def warning(self, msg): print(f"⚠️ {msg}")
|
||
def error(self, msg): print(f"❌ {msg}")
|
||
|
||
def __init__(self):
|
||
self.logger = self.Logger()
|
||
|
||
|
||
def calculate_komm_hash(kommunikationen):
|
||
"""Berechnet Hash wie im Code"""
|
||
komm_rowids = sorted([k.get('rowId', '') for k in kommunikationen if k.get('rowId')])
|
||
return hashlib.md5(''.join(komm_rowids).encode()).hexdigest()[:16]
|
||
|
||
|
||
async def compare_entities():
|
||
context = SimpleContext()
|
||
|
||
# IDs
|
||
betnr = 104860
|
||
espo_id = "68e3e7eab49f09adb"
|
||
|
||
print(f"\n{'='*80}")
|
||
print(f"ENTITY COMPARISON")
|
||
print(f"{'='*80}")
|
||
print(f"Advoware betNr: {betnr}")
|
||
print(f"EspoCRM ID: {espo_id}")
|
||
print(f"{'='*80}\n")
|
||
|
||
# Initialize APIs
|
||
advoware_api = AdvowareAPI(context)
|
||
advoware_service = AdvowareService(context)
|
||
espocrm = EspoCRMAPI(context)
|
||
mapper = BeteiligteMapper()
|
||
sync_utils = BeteiligteSync(espocrm, None, context)
|
||
|
||
# ========== FETCH ADVOWARE ==========
|
||
print("\n📥 Fetching Advoware Entity...")
|
||
try:
|
||
advo_result = await advoware_api.api_call(
|
||
f'api/v1/advonet/Beteiligte/{betnr}',
|
||
method='GET'
|
||
)
|
||
|
||
if isinstance(advo_result, list):
|
||
advo_entity = advo_result[0] if advo_result else None
|
||
else:
|
||
advo_entity = advo_result
|
||
|
||
if not advo_entity:
|
||
print("❌ Advoware Entity nicht gefunden!")
|
||
return
|
||
|
||
print(f"✅ Advoware Entity geladen")
|
||
print(f" - Name: {advo_entity.get('name')}")
|
||
print(f" - rowId: {advo_entity.get('rowId', 'N/A')[:40]}...")
|
||
print(f" - geaendertAm: {advo_entity.get('geaendertAm')}")
|
||
print(f" - Kommunikationen: {len(advo_entity.get('kommunikation', []))}")
|
||
|
||
except Exception as e:
|
||
print(f"❌ Fehler beim Laden von Advoware: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return
|
||
|
||
# ========== FETCH ESPOCRM ==========
|
||
print("\n📥 Fetching EspoCRM Entity...")
|
||
try:
|
||
espo_entity = await espocrm.get_entity('CBeteiligte', espo_id)
|
||
|
||
if not espo_entity:
|
||
print("❌ EspoCRM Entity nicht gefunden!")
|
||
return
|
||
|
||
print(f"✅ EspoCRM Entity geladen")
|
||
print(f" - Name: {espo_entity.get('name')}")
|
||
print(f" - betnr: {espo_entity.get('betnr')}")
|
||
print(f" - modifiedAt: {espo_entity.get('modifiedAt')}")
|
||
print(f" - syncStatus: {espo_entity.get('syncStatus')}")
|
||
print(f" - advowareLastSync: {espo_entity.get('advowareLastSync')}")
|
||
print(f" - advowareRowId: {espo_entity.get('advowareRowId', 'N/A')[:40]}...")
|
||
print(f" - kommunikationHash: {espo_entity.get('kommunikationHash')}")
|
||
print(f" - emailAddressData: {len(espo_entity.get('emailAddressData', []))}")
|
||
print(f" - phoneNumberData: {len(espo_entity.get('phoneNumberData', []))}")
|
||
|
||
except Exception as e:
|
||
print(f"❌ Fehler beim Laden von EspoCRM: {e}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return
|
||
|
||
# ========== COMPARISON ==========
|
||
print(f"\n{'='*80}")
|
||
print("STAMMDATEN VERGLEICH")
|
||
print(f"{'='*80}\n")
|
||
|
||
# Timestamp comparison
|
||
comparison = sync_utils.compare_entities(espo_entity, advo_entity)
|
||
print(f"🔍 Timestamp-Vergleich: {comparison}")
|
||
|
||
# Field-by-field comparison
|
||
print("\n📊 Feld-für-Feld Vergleich (Stammdaten):\n")
|
||
|
||
# Map Advoware → EspoCRM für Vergleich
|
||
advo_mapped = mapper.map_advoware_to_cbeteiligte(advo_entity)
|
||
|
||
fields_to_compare = [
|
||
'name', 'rechtsform', 'geburtsdatum', 'anrede',
|
||
'handelsregister', 'geschlecht', 'titel'
|
||
]
|
||
|
||
differences = []
|
||
for field in fields_to_compare:
|
||
espo_val = espo_entity.get(field)
|
||
advo_val = advo_mapped.get(field)
|
||
|
||
match = "✅" if espo_val == advo_val else "❌"
|
||
print(f"{match} {field:20} | EspoCRM: {str(espo_val)[:40]:40} | Advoware: {str(advo_val)[:40]:40}")
|
||
|
||
if espo_val != advo_val:
|
||
differences.append({
|
||
'field': field,
|
||
'espocrm': espo_val,
|
||
'advoware': advo_val
|
||
})
|
||
|
||
# ========== KOMMUNIKATION COMPARISON ==========
|
||
print(f"\n{'='*80}")
|
||
print("KOMMUNIKATION VERGLEICH")
|
||
print(f"{'='*80}\n")
|
||
|
||
advo_kommunikationen = advo_entity.get('kommunikation', [])
|
||
espo_emails = espo_entity.get('emailAddressData', [])
|
||
espo_phones = espo_entity.get('phoneNumberData', [])
|
||
|
||
# Hash Vergleich
|
||
current_hash = calculate_komm_hash(advo_kommunikationen)
|
||
stored_hash = espo_entity.get('kommunikationHash')
|
||
|
||
print(f"📊 Kommunikations-Hash:")
|
||
print(f" - Gespeichert in EspoCRM: {stored_hash}")
|
||
print(f" - Aktuell in Advoware: {current_hash}")
|
||
print(f" - Match: {'✅ JA' if current_hash == stored_hash else '❌ NEIN'}")
|
||
|
||
# Advoware Kommunikationen im Detail
|
||
print(f"\n📞 Advoware Kommunikationen ({len(advo_kommunikationen)}):")
|
||
for i, komm in enumerate(advo_kommunikationen, 1):
|
||
tlf = (komm.get('tlf') or '').strip()
|
||
kommkz = komm.get('kommKz', 0)
|
||
bemerkung = komm.get('bemerkung', '')[:50]
|
||
online = komm.get('online', False)
|
||
rowid = komm.get('rowId', 'N/A')[:20]
|
||
|
||
print(f" {i}. {tlf:30} | kommKz={kommkz:2} | online={online} | rowId={rowid}...")
|
||
if bemerkung:
|
||
print(f" Bemerkung: {bemerkung}...")
|
||
|
||
# EspoCRM Emails
|
||
print(f"\n📧 EspoCRM Emails ({len(espo_emails)}):")
|
||
for i, email in enumerate(espo_emails, 1):
|
||
addr = email.get('emailAddress', '')
|
||
primary = email.get('primary', False)
|
||
print(f" {i}. {addr:40} | primary={primary}")
|
||
|
||
# EspoCRM Phones
|
||
print(f"\n📱 EspoCRM Phones ({len(espo_phones)}):")
|
||
for i, phone in enumerate(espo_phones, 1):
|
||
num = phone.get('phoneNumber', '')
|
||
typ = phone.get('type', 'N/A')
|
||
primary = phone.get('primary', False)
|
||
print(f" {i}. {num:30} | type={typ:10} | primary={primary}")
|
||
|
||
# ========== SUMMARY ==========
|
||
print(f"\n{'='*80}")
|
||
print("ZUSAMMENFASSUNG")
|
||
print(f"{'='*80}\n")
|
||
|
||
if differences:
|
||
print(f"❌ STAMMDATEN NICHT SYNCHRON! {len(differences)} Unterschiede gefunden:")
|
||
for diff in differences:
|
||
print(f" - {diff['field']}: EspoCRM='{diff['espocrm']}' ≠ Advoware='{diff['advoware']}'")
|
||
else:
|
||
print("✅ Stammdaten sind synchron")
|
||
|
||
print()
|
||
|
||
if current_hash != stored_hash:
|
||
print(f"❌ KOMMUNIKATION NICHT SYNCHRON! Hash stimmt nicht überein")
|
||
else:
|
||
print("✅ Kommunikation-Hash stimmt überein (aber könnte trotzdem Unterschiede geben)")
|
||
|
||
print()
|
||
|
||
# Total count check
|
||
total_espo_komm = len(espo_emails) + len(espo_phones)
|
||
total_advo_komm = len([k for k in advo_kommunikationen if (k.get('tlf') or '').strip()])
|
||
|
||
if total_espo_komm != total_advo_komm:
|
||
print(f"⚠️ Anzahl-Unterschied: EspoCRM={total_espo_komm} ≠ Advoware={total_advo_komm}")
|
||
else:
|
||
print(f"✅ Anzahl stimmt überein: {total_espo_komm} Kommunikationen")
|
||
|
||
print(f"\n{'='*80}\n")
|
||
|
||
|
||
if __name__ == '__main__':
|
||
asyncio.run(compare_entities())
|