#!/usr/bin/env python3 """ Importiert "Schulden Niki.xlsx" ueber die REST API der Buchhaltungs-App. """ import openpyxl import uuid import json import urllib.request import urllib.error from datetime import datetime # API Konfiguration API_BASE = "http://localhost:3001/api" def read_excel_data(filepath): """Liest die Excel-Daten ein""" wb = openpyxl.load_workbook(filepath, data_only=True) ws = wb['Tabelle1'] data = [] headers = {} # Zeile 6: Headers for col_idx in range(1, 9): cell = ws.cell(row=6, column=col_idx) if cell.value: headers[cell.value] = col_idx print(f"Gefundene Spalten: {headers}") # Zeile 7+: Daten for row_idx in range(7, ws.max_row + 1): row_data = {} for header, col_idx in headers.items(): row_data[header] = ws.cell(row=row_idx, column=col_idx).value if row_data.get('Datum'): data.append(row_data) return data def api_call(endpoint, method='GET', data=None): """Fuehrt einen API-Call aus""" url = f"{API_BASE}{endpoint}" headers = {'Content-Type': 'application/json'} req = urllib.request.Request( url, data=json.dumps(data).encode() if data else None, headers=headers, method=method ) try: with urllib.request.urlopen(req, timeout=30) as response: return json.loads(response.read().decode()) except urllib.error.HTTPError as e: print(f"HTTP Error {e.code}: {e.read().decode()}") return None except Exception as e: print(f"Error: {e}") return None def get_monthly_rate(data): """Ermittelt die monatliche Rate aus den Daten""" rates = [] for row in data: abgezahlt = row.get('Abgezahlt') neue_kosten = row.get('Neue Kosten') if abgezahlt and abgezahlt > 0 and (not neue_kosten or neue_kosten == 0): rates.append(abgezahlt) if rates: from collections import Counter return Counter(rates).most_common(1)[0][0] return 0 def import_niki_schulden(): """Hauptimport-Funktion""" print("=" * 60) print("IMPORT: Schulden Niki (via API)") print("=" * 60) # 1. Excel-Daten lesen print("\n1. Lese Excel-Daten...") EXCEL_FILE = r'C:\Users\renet\.openclaw\workspace\buchhaltungs-app\Schulden Niki.xlsx' data = read_excel_data(EXCEL_FILE) print(f" {len(data)} Datensaetze gefunden") if not data: print(" KEINE DATEN GEFUNDEN!") return False first_row = data[0] start_datum = first_row.get('Datum') restschuld_start = abs(first_row.get('Restschuld', 0)) print(f" Startdatum: {start_datum}") print(f" Ursprungsschuld: {restschuld_start}") monatsrate = get_monthly_rate(data) print(f" Erkannte Monatsrate: {monatsrate}") # 2. Kredit erstellen print("\n2. Erstelle Kredit...") last_row = data[-1] restschuld_aktuell = abs(last_row.get('Restschuld', 0)) kredit_data = { 'name': 'Niki Schulden', 'kreditgeber': 'Rene Taeger', 'person': 'Niki', 'ursprungsschuld': float(restschuld_start), 'restschuld': float(restschuld_aktuell), 'monatsrate': float(monatsrate) if monatsrate > 0 else 0, 'zinssatz': 10.0, 'start_datum': start_datum.strftime('%Y-%m-%d') if hasattr(start_datum, 'strftime') else str(start_datum)[:10], 'status': 'aktiv' } print(f" Kredit-Daten: {json.dumps(kredit_data, indent=2)}") result = api_call('/kredite', method='POST', data=kredit_data) if not result: print(" [ERR] Fehler beim Erstellen des Kredits") return False kredit_id = result.get('id') print(f" [OK] Kredit erstellt mit ID: {kredit_id}") # 3. Zahlungen importieren (nutzt Endpunkt /kredite/{id}/zahlungen) print("\n3. Importiere Zahlungen...") zahlungen_count = 0 for idx, row in enumerate(data): datum = row.get('Datum') abgezahlt = row.get('Abgezahlt') or 0 neue_kosten = row.get('Neue Kosten') or 0 fuer_was = row.get('Fuer was', '') or row.get('F�r was', '') # Abgezahlt als Zahlung if abgezahlt and abgezahlt > 0: zahlung_data = { 'betrag': float(abgezahlt), 'datum': datum.strftime('%Y-%m-%d') if hasattr(datum, 'strftime') else str(datum)[:10], 'typ': 'monatsrate', 'notiz': fuer_was if fuer_was else 'Monatsrate' } result = api_call(f'/kredite/{kredit_id}/zahlungen', method='POST', data=zahlung_data) if result: zahlungen_count += 1 else: print(f" [ERR] Fehler bei Zahlung {idx + 1}") # Neue Kosten als Auslage if neue_kosten and neue_kosten < 0: zahlung_data = { 'betrag': float(abs(neue_kosten)), 'datum': datum.strftime('%Y-%m-%d') if hasattr(datum, 'strftime') else str(datum)[:10], 'typ': 'auslage', 'notiz': fuer_was if fuer_was else 'Auslage' } result = api_call(f'/kredite/{kredit_id}/zahlungen', method='POST', data=zahlung_data) if result: zahlungen_count += 1 else: print(f" [ERR] Fehler bei Auslage {idx + 1}") print(f" [OK] {zahlungen_count} Zahlungen importiert") # 4. Verifikation print("\n4. Verifikation:") result = api_call(f'/kredite/{kredit_id}/zahlungen') if result: print(f" Zahlungen in API: {len(result)}") result = api_call(f'/kredite/{kredit_id}') if result: db_restschuld = result.get('restschuld') print(f" Restschuld in DB: {db_restschuld}") print(f" Restschuld in Excel: {restschuld_aktuell}") if abs(float(db_restschuld) - float(restschuld_aktuell)) < 0.01: print(" [OK] Restschuld stimmt ueberein!") else: print(" [WARN] Restschuld weicht ab!") print("\n" + "=" * 60) print("IMPORT ABGESCHLOSSEN") print("=" * 60) return True if __name__ == '__main__': success = import_niki_schulden() exit(0 if success else 1)