#!/usr/bin/env python3 """ Detaillierte Analyse der Sync-Probleme für Entity 104860 """ import asyncio import sys import json from pathlib import Path import base64 sys.path.insert(0, str(Path(__file__).parent.parent)) from services.advoware import AdvowareAPI from services.espocrm import EspoCRMAPI from services.kommunikation_mapper import parse_marker, should_sync_to_espocrm class SimpleContext: class Logger: def info(self, msg): print(f"ℹ️ {msg}") def debug(self, msg): pass # Suppress debug 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() async def analyze(): context = SimpleContext() betnr = 104860 espo_id = "68e3e7eab49f09adb" # Initialize APIs advoware_api = AdvowareAPI(context) espocrm = EspoCRMAPI(context) # Fetch data advo_result = await advoware_api.api_call(f'api/v1/advonet/Beteiligte/{betnr}', method='GET') advo_entity = advo_result[0] if isinstance(advo_result, list) else advo_result espo_entity = await espocrm.get_entity('CBeteiligte', espo_id) print("\n" + "="*80) print("DETAILLIERTE SYNC-PROBLEM ANALYSE") print("="*80 + "\n") # ========== PROBLEM 1: NAME MISMATCH ========== print("🔴 PROBLEM 1: STAMMDATEN NICHT SYNCHRON") print("-" * 80) print(f"EspoCRM Name: '{espo_entity.get('name')}'") print(f"Advoware Name: '{advo_entity.get('name')}'") print(f"") print(f"ANALYSE:") print(f"- syncStatus: {espo_entity.get('syncStatus')}") print(f"- advowareLastSync: {espo_entity.get('advowareLastSync')}") print(f"- modifiedAt (EspoCRM): {espo_entity.get('modifiedAt')}") print(f"- geaendertAm (Advoware): {advo_entity.get('geaendertAm')}") print(f"") print(f"💡 URSACHE:") print(f" - Sync sagt 'clean' aber Daten sind NICHT identisch!") print(f" - Dies ist Problem #13: Keine Validierung von Sync-Ergebnissen") print(f" - Sync glaubt es war erfolgreich, aber Mapping oder API-Call fehlte") print() # ========== PROBLEM 2: KOMMUNIKATION COUNTS ========== print("🟡 PROBLEM 2: KOMMUNIKATION ANZAHL-MISMATCH") print("-" * 80) advo_kommunikationen = advo_entity.get('kommunikation', []) espo_emails = espo_entity.get('emailAddressData', []) espo_phones = espo_entity.get('phoneNumberData', []) # Analysiere Advoware Kommunikationen advo_with_value = [] advo_empty_slots = [] advo_non_sync = [] for komm in advo_kommunikationen: tlf = (komm.get('tlf') or '').strip() bemerkung = komm.get('bemerkung', '') marker = parse_marker(bemerkung) if not should_sync_to_espocrm(komm): advo_non_sync.append(komm) elif not tlf or (marker and marker.get('is_slot')): advo_empty_slots.append(komm) else: advo_with_value.append(komm) print(f"Advoware Kommunikationen: {len(advo_kommunikationen)} total") print(f" - Mit Wert (sollten in EspoCRM sein): {len(advo_with_value)}") print(f" - Empty Slots: {len(advo_empty_slots)}") print(f" - Nicht-sync-relevant: {len(advo_non_sync)}") print() print(f"EspoCRM Kommunikationen: {len(espo_emails) + len(espo_phones)} total") print(f" - Emails: {len(espo_emails)}") print(f" - Phones: {len(espo_phones)}") print() # Detaillierte Analyse der Empty Slots print("📋 Empty Slots in Advoware:") for i, slot in enumerate(advo_empty_slots, 1): marker = parse_marker(slot.get('bemerkung', '')) kommkz = marker.get('kommKz') if marker else 'N/A' rowid = slot.get('rowId', 'N/A')[:20] print(f" {i}. kommKz={kommkz} | rowId={rowid}... | bemerkung={slot.get('bemerkung', '')[:40]}") print() print("💡 URSACHE:") print(f" - {len(advo_empty_slots)} Empty Slots werden NICHT aufgeräumt") print(f" - Dies ist Problem #2: Empty Slot Accumulation") print(f" - Nur {len(advo_with_value)} Einträge mit Wert, aber Hash beinhaltet ALLE {len(advo_kommunikationen)}") print() # ========== PROBLEM 3: MARKER ANALYSIS ========== print("🟡 PROBLEM 3: MARKER VALIDIERUNG") print("-" * 80) marker_issues = [] for komm in advo_with_value: tlf = (komm.get('tlf') or '').strip() bemerkung = komm.get('bemerkung', '') marker = parse_marker(bemerkung) if marker: synced_value = marker.get('synced_value', '') if synced_value != tlf: marker_issues.append({ 'tlf': tlf, 'synced_value': synced_value, 'marker': bemerkung[:50] }) if marker_issues: print(f"❌ {len(marker_issues)} Marker stimmen NICHT mit aktuellem Wert überein:") for issue in marker_issues: print(f" - Aktuell: '{issue['tlf']}'") print(f" Marker: '{issue['synced_value']}'") print(f" Marker-String: {issue['marker']}...") print() print("💡 URSACHE:") print(" - Dies deutet auf Problem #6: Marker-Update fehlgeschlagen") print(" - Oder Var6 wurde erkannt aber Marker nicht aktualisiert") else: print("✅ Alle Marker stimmen mit aktuellen Werten überein") print() # ========== PROBLEM 4: HASH COVERAGE ========== print("🟡 PROBLEM 4: HASH-BERECHNUNG") print("-" * 80) import hashlib # Aktueller Code (FALSCH - beinhaltet ALLE) all_rowids = sorted([k.get('rowId', '') for k in advo_kommunikationen if k.get('rowId')]) wrong_hash = hashlib.md5(''.join(all_rowids).encode()).hexdigest()[:16] # Korrekt (nur sync-relevante) sync_relevant_komm = [k for k in advo_kommunikationen if should_sync_to_espocrm(k) and (k.get('tlf') or '').strip()] sync_rowids = sorted([k.get('rowId', '') for k in sync_relevant_komm if k.get('rowId')]) correct_hash = hashlib.md5(''.join(sync_rowids).encode()).hexdigest()[:16] stored_hash = espo_entity.get('kommunikationHash') print(f"Hash-Vergleich:") print(f" - Gespeichert: {stored_hash}") print(f" - Aktuell (ALL): {wrong_hash} {'✅' if wrong_hash == stored_hash else '❌'}") print(f" - Korrekt (nur sync-relevant): {correct_hash} {'✅' if correct_hash == stored_hash else '❌'}") print() print(f"Rowids einbezogen:") print(f" - ALL: {len(all_rowids)} Kommunikationen") print(f" - Sync-relevant: {len(sync_rowids)} Kommunikationen") print() print("💡 URSACHE:") print(" - Dies ist Problem #3: Hash beinhaltet ALLE statt nur sync-relevante") print(" - Empty Slots ändern Hash obwohl sie nicht in EspoCRM sind") print() # ========== ZUSAMMENFASSUNG ========== print("="*80) print("ZUSAMMENFASSUNG DER PROBLEME") print("="*80) print() print("✅ BESTÄTIGT - Die folgenden Probleme existieren:") print() print("1. ❌ Problem #13: Keine Validierung von Sync-Ergebnissen") print(" → Stammdaten sind NICHT synchron obwohl syncStatus='clean'") print() print("2. ❌ Problem #2: Empty Slot Accumulation") print(f" → {len(advo_empty_slots)} Empty Slots sammeln sich an") print() print("3. ❌ Problem #3: Hash-Berechnung inkorrekt") print(f" → Hash beinhaltet {len(all_rowids)} statt {len(sync_rowids)} Kommunikationen") print() if marker_issues: print("4. ❌ Problem #6: Marker-Update Failures") print(f" → {len(marker_issues)} Marker stimmen nicht mit aktuellem Wert überein") print() print("="*80) if __name__ == '__main__': asyncio.run(analyze())