#!/usr/bin/env python3 """ Test: gueltigBis nachträglich setzen und entfernen (Soft-Delete) ================================================================== Ziele: 1. Teste ob gueltigBis via PUT gesetzt werden kann (Deaktivierung) 2. Teste ob gueltigBis via PUT entfernt werden kann (Reaktivierung) 3. Teste ob gueltigBis auf null/None gesetzt werden kann """ import asyncio import sys import os from datetime import datetime # Add parent directory to path sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..')) from services.advoware import AdvowareAPI # Test-Konfiguration TEST_BETNR = 104860 # ANSI Color codes BOLD = '\033[1m' RED = '\033[91m' GREEN = '\033[92m' YELLOW = '\033[93m' BLUE = '\033[94m' RESET = '\033[0m' def print_header(text): print(f"\n{BOLD}{'='*80}{RESET}") print(f"{BOLD}{text}{RESET}") print(f"{BOLD}{'='*80}{RESET}\n") def print_success(text): print(f"{GREEN}✓ {text}{RESET}") def print_error(text): print(f"{RED}✗ {text}{RESET}") def print_warning(text): print(f"{YELLOW}⚠ {text}{RESET}") def print_info(text): print(f"{BLUE}ℹ {text}{RESET}") class SimpleLogger: def info(self, msg): pass def error(self, msg): print_error(msg) def debug(self, msg): pass def warning(self, msg): pass class SimpleContext: def __init__(self): self.logger = SimpleLogger() def log_info(self, msg): pass def log_error(self, msg): print_error(msg) def log_debug(self, msg): pass async def test_1_create_active_address(): """Test 1: Erstelle aktive Adresse (ohne gueltigBis)""" print_header("TEST 1: Erstelle aktive Adresse (OHNE gueltigBis)") context = SimpleContext() advo = AdvowareAPI(context=context) address_data = { "strasse": "Soft-Delete Test Straße", "plz": "66666", "ort": "Teststadt", "land": "DE", "bemerkung": "TEST-SOFTDELETE: Für gueltigBis Modifikation", "gueltigVon": "2026-01-01T00:00:00" # KEIN gueltigBis → unbegrenzt gültig } print_info("Erstelle Adresse OHNE gueltigBis (unbegrenzt aktiv)...") try: result = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='POST', json_data=address_data ) if result and len(result) > 0: addr = result[0] print_success(f"✓ Adresse erstellt") print_info(f" rowId: {addr.get('rowId')}") print_info(f" gueltigVon: {addr.get('gueltigVon')}") print_info(f" gueltigBis: {addr.get('gueltigBis')} (sollte None sein)") # Hole echten Index via GET all_addresses = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='GET' ) for a in all_addresses: if (a.get('bemerkung') or '').startswith('TEST-SOFTDELETE'): print_info(f" reihenfolgeIndex: {a.get('reihenfolgeIndex')}") return a.get('reihenfolgeIndex') return None else: print_error("POST fehlgeschlagen") return None except Exception as e: print_error(f"Fehler: {e}") import traceback traceback.print_exc() return None async def test_2_deactivate_via_gueltigbis(index): """Test 2: Deaktiviere Adresse durch Setzen von gueltigBis""" print_header("TEST 2: Deaktivierung - gueltigBis nachträglich setzen") context = SimpleContext() advo = AdvowareAPI(context=context) try: # Hole aktuelle Adresse all_addresses = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='GET' ) test_addr = next((a for a in all_addresses if a.get('reihenfolgeIndex') == index), None) if not test_addr: print_error(f"Adresse mit Index {index} nicht gefunden") return False print_info("Status VORHER:") print(f" gueltigVon: {test_addr.get('gueltigVon')}") print(f" gueltigBis: {test_addr.get('gueltigBis')}") # Setze gueltigBis auf gestern (= deaktiviert) print_info("\nSetze gueltigBis auf 2024-12-31 (Vergangenheit = deaktiviert)...") update_data = { "strasse": test_addr.get('strasse'), "plz": test_addr.get('plz'), "ort": test_addr.get('ort'), "land": test_addr.get('land'), "gueltigVon": test_addr.get('gueltigVon'), "gueltigBis": "2024-12-31T23:59:59" # ← Vergangenheit } result = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen/{index}', method='PUT', json_data=update_data ) print_success("✓ PUT erfolgreich") # Prüfe Ergebnis print_info("\nHole Adresse erneut und prüfe gueltigBis...") all_addresses = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='GET' ) updated_addr = next((a for a in all_addresses if a.get('reihenfolgeIndex') == index), None) if updated_addr: print_info("Status NACHHER:") print(f" gueltigVon: {updated_addr.get('gueltigVon')}") print(f" gueltigBis: {updated_addr.get('gueltigBis')}") if updated_addr.get('gueltigBis') == "2024-12-31T00:00:00": print_success("\n✓✓✓ PERFEKT: gueltigBis wurde nachträglich gesetzt!") print_success("✓ Adresse kann via PUT deaktiviert werden!") return True else: print_error(f"\n❌ gueltigBis nicht korrekt: {updated_addr.get('gueltigBis')}") return False else: print_error("Adresse nach PUT nicht gefunden") return False except Exception as e: print_error(f"Fehler: {e}") import traceback traceback.print_exc() return False async def test_3_reactivate_set_far_future(index): """Test 3: Reaktivierung durch Setzen auf weit in Zukunft""" print_header("TEST 3: Reaktivierung - gueltigBis auf fernes Datum setzen") context = SimpleContext() advo = AdvowareAPI(context=context) try: # Hole aktuelle Adresse all_addresses = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='GET' ) test_addr = next((a for a in all_addresses if a.get('reihenfolgeIndex') == index), None) if not test_addr: print_error(f"Adresse mit Index {index} nicht gefunden") return False print_info("Status VORHER (deaktiviert):") print(f" gueltigBis: {test_addr.get('gueltigBis')}") # Setze gueltigBis auf weit in Zukunft print_info("\nSetze gueltigBis auf 2099-12-31 (weit in Zukunft = aktiv)...") update_data = { "strasse": test_addr.get('strasse'), "plz": test_addr.get('plz'), "ort": test_addr.get('ort'), "land": test_addr.get('land'), "gueltigVon": test_addr.get('gueltigVon'), "gueltigBis": "2099-12-31T23:59:59" # ← Weit in Zukunft } await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen/{index}', method='PUT', json_data=update_data ) print_success("✓ PUT erfolgreich") # Prüfe Ergebnis print_info("\nHole Adresse erneut...") all_addresses = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='GET' ) updated_addr = next((a for a in all_addresses if a.get('reihenfolgeIndex') == index), None) if updated_addr: print_info("Status NACHHER (reaktiviert):") print(f" gueltigBis: {updated_addr.get('gueltigBis')}") if updated_addr.get('gueltigBis') == "2099-12-31T00:00:00": print_success("\n✓✓✓ PERFEKT: gueltigBis wurde auf Zukunft gesetzt!") print_success("✓ Adresse ist jetzt wieder aktiv!") return True else: print_error(f"\n❌ gueltigBis nicht korrekt: {updated_addr.get('gueltigBis')}") return False else: print_error("Adresse nach PUT nicht gefunden") return False except Exception as e: print_error(f"Fehler: {e}") import traceback traceback.print_exc() return False async def test_4_remove_gueltigbis_completely(index): """Test 4: Entferne gueltigBis komplett (null/None)""" print_header("TEST 4: gueltigBis komplett entfernen (null/None)") context = SimpleContext() advo = AdvowareAPI(context=context) try: # Hole aktuelle Adresse all_addresses = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='GET' ) test_addr = next((a for a in all_addresses if a.get('reihenfolgeIndex') == index), None) if not test_addr: print_error(f"Adresse mit Index {index} nicht gefunden") return None print_info("Status VORHER:") print(f" gueltigBis: {test_addr.get('gueltigBis')}") # Versuche 1: gueltigBis weglassen print_info("\n=== Versuch 1: gueltigBis komplett weglassen ===") update_data = { "strasse": test_addr.get('strasse'), "plz": test_addr.get('plz'), "ort": test_addr.get('ort'), "land": test_addr.get('land'), "gueltigVon": test_addr.get('gueltigVon') # gueltigBis absichtlich weggelassen } await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen/{index}', method='PUT', json_data=update_data ) all_addresses = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='GET' ) updated_addr = next((a for a in all_addresses if a.get('reihenfolgeIndex') == index), None) result_1 = updated_addr.get('gueltigBis') if updated_addr else "ERROR" print_info(f"Ergebnis: gueltigBis = {result_1}") if result_1 is None: print_success("✓ Weglassen entfernt gueltigBis!") return "omit" # Versuche 2: gueltigBis = None/null print_info("\n=== Versuch 2: gueltigBis explizit auf None setzen ===") update_data['gueltigBis'] = None await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen/{index}', method='PUT', json_data=update_data ) all_addresses = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='GET' ) updated_addr = next((a for a in all_addresses if a.get('reihenfolgeIndex') == index), None) result_2 = updated_addr.get('gueltigBis') if updated_addr else "ERROR" print_info(f"Ergebnis: gueltigBis = {result_2}") if result_2 is None: print_success("✓ None entfernt gueltigBis!") return "none" # Versuche 3: gueltigBis = "" print_info("\n=== Versuch 3: gueltigBis auf leeren String setzen ===") update_data['gueltigBis'] = "" try: await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen/{index}', method='PUT', json_data=update_data ) all_addresses = await advo.api_call( f'/api/v1/advonet/Beteiligte/{TEST_BETNR}/Adressen', method='GET' ) updated_addr = next((a for a in all_addresses if a.get('reihenfolgeIndex') == index), None) result_3 = updated_addr.get('gueltigBis') if updated_addr else "ERROR" print_info(f"Ergebnis: gueltigBis = {result_3}") if result_3 is None: print_success("✓ Leerer String entfernt gueltigBis!") return "empty" except Exception as e: print_warning(f"⚠ Leerer String wird abgelehnt: {e}") print_warning("\n⚠ gueltigBis kann nicht komplett entfernt werden") print_info("💡 Lösung: Setze auf weit in Zukunft (2099-12-31) für 'unbegrenzt aktiv'") return "not_possible" except Exception as e: print_error(f"Fehler: {e}") import traceback traceback.print_exc() return None async def main(): print(f"\n{BOLD}╔══════════════════════════════════════════════════════════════╗{RESET}") print(f"{BOLD}║ gueltigBis nachträglich ändern (Soft-Delete Tests) ║{RESET}") print(f"{BOLD}╚══════════════════════════════════════════════════════════════╝{RESET}\n") print(f"Test-Konfiguration:") print(f" BetNr: {TEST_BETNR}") print(f" Datum: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}") # Test 1: Erstelle aktive Adresse index = await test_1_create_active_address() if not index: print_error("\nTest abgebrochen: Konnte Adresse nicht erstellen") return # Test 2: Deaktiviere via gueltigBis can_deactivate = await test_2_deactivate_via_gueltigbis(index) # Test 3: Reaktiviere via gueltigBis auf Zukunft can_reactivate = await test_3_reactivate_set_far_future(index) # Test 4: Versuche gueltigBis zu entfernen remove_method = await test_4_remove_gueltigbis_completely(index) # Finale Zusammenfassung print(f"\n{BOLD}╔══════════════════════════════════════════════════════════════╗{RESET}") print(f"{BOLD}║ FINALE ERKENNTNISSE ║{RESET}") print(f"{BOLD}╚══════════════════════════════════════════════════════════════╝{RESET}\n") print(f"{BOLD}Soft-Delete Funktionalität:{RESET}\n") if can_deactivate: print_success("✓✓✓ DEAKTIVIERUNG funktioniert:") print_success(" • gueltigBis kann via PUT auf Vergangenheit gesetzt werden") print_success(" • Beispiel: gueltigBis = '2024-12-31T23:59:59'") print_success(" • Adresse bleibt in GET sichtbar (Client-Filter nötig)") else: print_error("✗ DEAKTIVIERUNG funktioniert NICHT") print() if can_reactivate: print_success("✓✓✓ REAKTIVIERUNG funktioniert:") print_success(" • gueltigBis kann via PUT auf Zukunft gesetzt werden") print_success(" • Beispiel: gueltigBis = '2099-12-31T23:59:59'") print_success(" • Adresse ist damit wieder aktiv") else: print_error("✗ REAKTIVIERUNG funktioniert NICHT") print() if remove_method: if remove_method in ["omit", "none", "empty"]: print_success(f"✓ gueltigBis entfernen funktioniert (Methode: {remove_method})") if remove_method == "omit": print_success(" • Weglassen des Feldes entfernt gueltigBis") elif remove_method == "none": print_success(" • Setzen auf None/null entfernt gueltigBis") elif remove_method == "empty": print_success(" • Setzen auf '' entfernt gueltigBis") else: print_warning("⚠ gueltigBis kann NICHT komplett entfernt werden") print_info(" • Lösung: Setze auf 2099-12-31 für 'unbegrenzt aktiv'") print(f"\n{BOLD}Empfohlener Workflow:{RESET}\n") print_info("1. AKTIV (Standard):") print_info(" → gueltigBis = '2099-12-31T23:59:59' oder None") print_info(" → In EspoCRM: isActive = True") print() print_info("2. DEAKTIVIEREN (Soft-Delete):") print_info(" → PUT mit gueltigBis = '2024-01-01T00:00:00' (Vergangenheit)") print_info(" → In EspoCRM: isActive = False") print() print_info("3. REAKTIVIEREN:") print_info(" → PUT mit gueltigBis = '2099-12-31T23:59:59' (Zukunft)") print_info(" → In EspoCRM: isActive = True") print() print_info("4. SYNC LOGIC:") print_info(" → GET /Adressen → filter wo gueltigBis > heute") print_info(" → Sync nur aktive Adressen nach EspoCRM") print_info(" → Update isActive basierend auf gueltigBis") print(f"\n{YELLOW}⚠️ ACHTUNG: Test-Adresse 'TEST-SOFTDELETE' sollte bereinigt werden.{RESET}\n") if __name__ == "__main__": asyncio.run(main())