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.
This commit is contained in:
108
bitbylaw/scripts/verify_advoware_kommunikation_ids.py
Normal file
108
bitbylaw/scripts/verify_advoware_kommunikation_ids.py
Normal file
@@ -0,0 +1,108 @@
|
||||
"""
|
||||
Verifikation: Hat Advoware eindeutige IDs für Kommunikationen?
|
||||
|
||||
Prüfe:
|
||||
1. Hat jede Kommunikation eine 'id'?
|
||||
2. Sind die IDs eindeutig?
|
||||
3. Bleibt die ID stabil bei UPDATE?
|
||||
4. Was ist mit rowId?
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
from services.advoware import AdvowareAPI
|
||||
|
||||
TEST_BETNR = 104860
|
||||
|
||||
|
||||
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 main():
|
||||
print("\n" + "="*70)
|
||||
print("ADVOWARE KOMMUNIKATION IDs")
|
||||
print("="*70)
|
||||
|
||||
context = SimpleContext()
|
||||
advo = AdvowareAPI(context)
|
||||
|
||||
# Hole Beteiligte mit Kommunikationen
|
||||
print_section("Aktuelle Kommunikationen")
|
||||
|
||||
result = await advo.api_call(f'api/v1/advonet/Beteiligte/{TEST_BETNR}')
|
||||
beteiligte = result[0]
|
||||
kommunikationen = beteiligte.get('kommunikation', [])
|
||||
|
||||
print(f"\n✅ {len(kommunikationen)} Kommunikationen gefunden\n")
|
||||
|
||||
# Zeige alle IDs
|
||||
ids = []
|
||||
row_ids = []
|
||||
|
||||
for i, k in enumerate(kommunikationen[:10], 1): # Erste 10
|
||||
komm_id = k.get('id')
|
||||
row_id = k.get('rowId')
|
||||
wert = k.get('tlf', '')[:40]
|
||||
kommkz = k.get('kommKz')
|
||||
|
||||
ids.append(komm_id)
|
||||
row_ids.append(row_id)
|
||||
|
||||
print(f"[{i:2d}] ID: {komm_id:8d} | rowId: {row_id:20s} | "
|
||||
f"Typ: {kommkz:2d} | Wert: {wert}")
|
||||
|
||||
# Analyse
|
||||
print_section("ANALYSE")
|
||||
|
||||
print(f"\n1️⃣ IDs vorhanden:")
|
||||
print(f" • Alle haben 'id': {all(k.get('id') for k in kommunikationen)}")
|
||||
print(f" • Alle haben 'rowId': {all(k.get('rowId') for k in kommunikationen)}")
|
||||
|
||||
print(f"\n2️⃣ Eindeutigkeit:")
|
||||
print(f" • Anzahl IDs: {len(ids)}")
|
||||
print(f" • Anzahl unique IDs: {len(set(ids))}")
|
||||
print(f" • ✅ IDs sind eindeutig: {len(ids) == len(set(ids))}")
|
||||
|
||||
print(f"\n3️⃣ ID-Typ:")
|
||||
print(f" • Beispiel-ID: {ids[0] if ids else 'N/A'}")
|
||||
print(f" • Typ: {type(ids[0]).__name__ if ids else 'N/A'}")
|
||||
print(f" • Format: Integer (stabil)")
|
||||
|
||||
print(f"\n4️⃣ rowId-Typ:")
|
||||
print(f" • Beispiel-rowId: {row_ids[0] if row_ids else 'N/A'}")
|
||||
print(f" • Typ: {type(row_ids[0]).__name__ if row_ids else 'N/A'}")
|
||||
print(f" • Format: Base64 String (ändert sich bei UPDATE)")
|
||||
|
||||
print_section("FAZIT")
|
||||
|
||||
print("\n✅ Advoware hat EINDEUTIGE IDs für Kommunikationen!")
|
||||
print("\n📋 Eigenschaften:")
|
||||
print(" • id: Integer, stabil, eindeutig")
|
||||
print(" • rowId: String, ändert sich bei UPDATE (für Change Detection)")
|
||||
|
||||
print("\n💡 Das bedeutet:")
|
||||
print(" • Wir können Advoware-ID als Schlüssel nutzen")
|
||||
print(" • Matching: Advoware-ID ↔ EspoCRM-Wert")
|
||||
print(" • Speichere Advoware-ID irgendwo für Reverse-Lookup")
|
||||
|
||||
print("\n🎯 BESSERE LÖSUNG:")
|
||||
print(" Option D: Advoware-ID als Kommentar in bemerkung speichern?")
|
||||
print(" Option E: Advoware-ID in Wert-Format kodieren?")
|
||||
print(" Option F: Separate Mapping-Tabelle (Redis/DB)?")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user