Files
buchhaltung/import_via_api.py
T
2026-04-26 07:51:39 +02:00

204 lines
6.3 KiB
Python

#!/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('Fr 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)