feat: Implement address synchronization between EspoCRM and Advoware

- Add AdressenMapper for transforming addresses between EspoCRM and Advoware formats.
- Create AdressenSync class to handle address creation, update, and deletion synchronization.
- Introduce NotificationManager for managing manual intervention notifications in case of sync issues.
- Implement detailed logging for address sync operations and error handling.
- Ensure READ-ONLY field changes are detected and notified for manual resolution.
This commit is contained in:
2026-02-08 14:29:29 +00:00
parent 68c8b398aa
commit c770f2c8ee
15 changed files with 6427 additions and 0 deletions

View File

@@ -0,0 +1,189 @@
#!/usr/bin/env python3
"""
Test: Finde "Test 6667426" Adresse in API
====================================
User sagt: In Advoware wird "Test 6667426" als Hauptadresse angezeigt
Ziel: API-Response dieser Adresse analysieren
"""
import asyncio
import json
import sys
import os
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..'))
from services.advoware import AdvowareAPI
# Farben für Output
GREEN = '\033[92m'
RED = '\033[91m'
YELLOW = '\033[93m'
BLUE = '\033[94m'
BOLD = '\033[1m'
RESET = '\033[0m'
BETNR = 104860
class SimpleLogger:
def info(self, msg): pass
def error(self, msg): pass
def warning(self, msg): pass
def debug(self, msg): pass
class SimpleContext:
def __init__(self):
self.logger = SimpleLogger()
def print_section(title):
print(f"\n{BLUE}{BOLD}{'='*70}{RESET}")
print(f"{BLUE}{BOLD}{title}{RESET}")
print(f"{BLUE}{BOLD}{'='*70}{RESET}\n")
def print_success(msg):
print(f"{GREEN}{msg}{RESET}")
def print_error(msg):
print(f"{RED}{msg}{RESET}")
def print_info(msg):
print(f"{YELLOW} {msg}{RESET}")
async def main():
print_section("Suche 'Test 6667426' Adresse in API")
# Initialize API
context = SimpleContext()
api = AdvowareAPI(context=context)
# Hole alle Adressen
adressen = await api.api_call(
f'/api/v1/advonet/Beteiligte/{BETNR}/Adressen',
method='GET'
)
if not adressen:
print_error("Keine Adressen gefunden!")
return
print_info(f"Gefunden: {len(adressen)} Adressen")
# Suche nach "Test 6667426"
target_addr = None
for addr in adressen:
strasse = addr.get('strasse', '') or ''
anschrift = addr.get('anschrift', '') or ''
if '6667426' in strasse or '6667426' in anschrift:
target_addr = addr
break
if not target_addr:
print_error("Adresse 'Test 6667426' NICHT gefunden!")
print_info("Suche nach 'Test' in Adress-Feldern...")
# Zeige alle Adressen mit "Test"
test_adressen = []
for addr in adressen:
strasse = addr.get('strasse', '')
if 'Test' in strasse:
test_adressen.append(addr)
if test_adressen:
print_info(f"Gefunden: {len(test_adressen)} Adressen mit 'Test':")
for addr in test_adressen:
print(f" - Index: {addr.get('reihenfolgeIndex')}, "
f"Strasse: {addr.get('strasse')}, "
f"standardAnschrift: {addr.get('standardAnschrift')}")
return
# Zeige vollständige Adresse
print_section("GEFUNDEN: Test 6667426")
print(f"{BOLD}Vollständiger API-Response:{RESET}")
print(json.dumps(target_addr, indent=2, ensure_ascii=False))
# Analysiere wichtige Felder
print_section("Wichtige Felder")
wichtige_felder = [
'id',
'rowId',
'reihenfolgeIndex',
'strasse',
'plz',
'ort',
'anschrift',
'standardAnschrift', # ← Das ist der Key!
'bemerkung',
'gueltigVon',
'gueltigBis'
]
for feld in wichtige_felder:
wert = target_addr.get(feld)
# Highlight standardAnschrift
if feld == 'standardAnschrift':
if wert:
print(f" {GREEN}{BOLD}{feld}: {wert}{RESET} ← HAUPTADRESSE!")
else:
print(f" {RED}{BOLD}{feld}: {wert}{RESET} ← NICHT Hauptadresse!")
else:
print(f" {feld}: {wert}")
# Vergleiche mit anderen Adressen
print_section("Vergleich mit anderen Adressen")
hauptadressen = [a for a in adressen if a.get('standardAnschrift')]
print_info(f"Anzahl Adressen mit standardAnschrift=true: {len(hauptadressen)}")
if len(hauptadressen) == 0:
print_error("KEINE einzige Adresse hat standardAnschrift=true!")
print_info("Aber Advoware zeigt trotzdem eine als 'Haupt' an?")
elif len(hauptadressen) == 1:
if hauptadressen[0] == target_addr:
print_success("Test 6667426 ist die EINZIGE Hauptadresse!")
else:
print_error("Test 6667426 ist NICHT die Hauptadresse!")
print_info(f"Hauptadresse ist: {hauptadressen[0].get('strasse')}")
else:
print_error(f"MEHRERE Hauptadressen ({len(hauptadressen)})!")
for ha in hauptadressen:
marker = " ← Das ist Test 6667426!" if ha == target_addr else ""
print(f" - Index {ha.get('reihenfolgeIndex')}: {ha.get('strasse')}{marker}")
# Prüfe ob es die neueste ist
print_section("Position/Reihenfolge")
max_index = max(a.get('reihenfolgeIndex', 0) for a in adressen)
target_index = target_addr.get('reihenfolgeIndex')
print_info(f"Test 6667426 hat Index: {target_index}")
print_info(f"Höchster Index: {max_index}")
if target_index == max_index:
print_success("Test 6667426 ist die NEUESTE Adresse (höchster Index)!")
else:
print_error(f"Test 6667426 ist NICHT die neueste (Differenz: {max_index - target_index})")
# Sortierung nach Index
sorted_adressen = sorted(adressen, key=lambda a: a.get('reihenfolgeIndex', 0))
print_info(f"\nAlle Adressen sortiert nach reihenfolgeIndex:")
for i, addr in enumerate(sorted_adressen[-10:]): # Zeige letzte 10
idx = addr.get('reihenfolgeIndex')
strasse = addr.get('strasse', '')[:40]
standard = addr.get('standardAnschrift')
marker = ""
if addr == target_addr:
marker = f" {GREEN}← Test 6667426{RESET}"
standard_marker = f"{GREEN}[HAUPT]{RESET}" if standard else ""
print(f" {idx:3d}: {strasse:40s} {standard_marker}{marker}")
if __name__ == '__main__':
asyncio.run(main())