Initial commit - Stand 26.04.2026

This commit is contained in:
OpenClaw
2026-04-26 07:51:39 +02:00
commit b29c467187
186 changed files with 39281 additions and 0 deletions
+240
View File
@@ -0,0 +1,240 @@
#!/usr/bin/env python3
"""
Importiert "Schulden Niki.xlsx" in die Buchhaltungsdatenbank.
Erstellt einen Kredit und importiert alle Zahlungen/Auslagen.
"""
import openpyxl
import psycopg2
import uuid
from datetime import datetime
from pathlib import Path
# Konfiguration
DB_CONFIG = {
'host': '192.168.2.200',
'port': 5432,
'database': 'postgres',
'user': 'postgres',
'password': 'postgres' # Passwort aus .env
}
EXCEL_FILE = r'C:\Users\renet\.openclaw\workspace\buchhaltungs-app\Schulden Niki.xlsx'
def connect_db():
"""Verbindet zur Datenbank"""
return psycopg2.connect(**DB_CONFIG)
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
# Nur Zeilen mit Datum verarbeiten
if row_data.get('Datum'):
data.append(row_data)
return data, headers
def determine_payment_type(abgezahlt, neue_kosten, fuer_was):
"""
Bestimmt den Zahlungstyp:
- monatsrate: Regelmäßige Rate
- sondertilgung: Zusätzliche Tilgung
- auslage: Neue Kosten/Auslagen
"""
if neue_kosten and neue_kosten != 0:
return 'auslage'
elif fuer_was and ('tilgung' in str(fuer_was).lower() or 'sonder' in str(fuer_was).lower()):
return 'sondertilgung'
elif abgezahlt and abgezahlt > 0:
return 'monatsrate'
return 'sondertilgung' # Fallback
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')
# Nur regelmäßige Zahlungen (positive Abgezahlt-Werte)
if abgezahlt and abgezahlt > 0 and (not neue_kosten or neue_kosten == 0):
rates.append(abgezahlt)
# Häufigster Wert = Rate
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")
print("=" * 60)
# 1. Excel-Daten lesen
print("\n1. Lese Excel-Daten...")
data, headers = read_excel_data(EXCEL_FILE)
print(f" {len(data)} Datensätze gefunden")
if not data:
print(" KEINE DATEN GEFUNDEN!")
return False
# Erste Zeile analysieren
first_row = data[0]
start_datum = first_row.get('Datum')
restschuld_start = abs(first_row.get('Restschuld', 0)) # Negativ = Schulden
print(f" Startdatum: {start_datum}")
print(f" Ursprungsschuld: {restschuld_start}")
# Rate ermitteln
monatsrate = get_monthly_rate(data)
print(f" Erkannte Monatsrate: {monatsrate}")
# 2. Datenbankverbindung
print("\n2. Verbinde zur Datenbank...")
conn = connect_db()
cursor = conn.cursor()
try:
# 3. Kredit erstellen
print("\n3. Erstelle Kredit...")
kredit_id = str(uuid.uuid4())
# Aktuelle Restschuld aus letzter Zeile
last_row = data[-1]
restschuld_aktuell = abs(last_row.get('Restschuld', 0))
cursor.execute("""
INSERT INTO kredite (
id, name, kreditgeber, person,
ursprungsschuld, restschuld, monatsrate,
zinssatz, start_datum, status, notizen
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
""", (
kredit_id,
'Niki Schulden',
'René Täger', # Kreditgeber
'Niki', # Person
restschuld_start,
restschuld_aktuell,
monatsrate if monatsrate > 0 else 0,
10.0, # Zinssatz 10%
start_datum.date() if hasattr(start_datum, 'date') else start_datum,
'aktiv',
'Importiert aus Excel "Schulden Niki.xlsx" am ' + datetime.now().strftime('%Y-%m-%d')
))
print(f" Kredit-ID: {kredit_id}")
print(f" Name: Niki Schulden")
print(f" Ursprungsschuld: {restschuld_start:.2f}")
print(f" Aktuelle Restschuld: {restschuld_aktuell:.2f}")
# 4. Zahlungen importieren
print("\n4. Importiere Zahlungen...")
zahlungen_count = 0
for row in data:
datum = row.get('Datum')
abgezahlt = row.get('Abgezahlt') or 0
neue_kosten = row.get('Neue Kosten') or 0
fuer_was = row.get('Für was', '')
# Abgezahlt als positive Zahlung
if abgezahlt and abgezahlt > 0:
zahlung_id = str(uuid.uuid4())
typ = determine_payment_type(abgezahlt, None, fuer_was)
cursor.execute("""
INSERT INTO kredit_zahlungen (
id, kredit_id, betrag, datum, typ, notiz
) VALUES (%s, %s, %s, %s, %s, %s)
""", (
zahlung_id,
kredit_id,
abgezahlt,
datum.date() if hasattr(datum, 'date') else datum,
typ,
fuer_was if fuer_was else f'{typ.capitalize()}'
))
zahlungen_count += 1
# Neue Kosten als Auslage (negativer Betrag = mehr Schulden)
if neue_kosten and neue_kosten < 0:
zahlung_id = str(uuid.uuid4())
cursor.execute("""
INSERT INTO kredit_zahlungen (
id, kredit_id, betrag, datum, typ, notiz
) VALUES (%s, %s, %s, %s, %s, %s)
""", (
zahlung_id,
kredit_id,
abs(neue_kosten), # Absolutwert für den Betrag
datum.date() if hasattr(datum, 'date') else datum,
'auslage',
fuer_was if fuer_was else 'Auslage'
))
zahlungen_count += 1
print(f" {zahlungen_count} Zahlungen importiert")
# 5. Commit
conn.commit()
print("\n5. Import erfolgreich abgeschlossen!")
# 6. Verifikation
print("\n6. Verifikation:")
cursor.execute("SELECT COUNT(*) FROM kredit_zahlungen WHERE kredit_id = %s", (kredit_id,))
count = cursor.fetchone()[0]
print(f" Zahlungen in Datenbank: {count}")
cursor.execute("SELECT restschuld FROM kredite WHERE id = %s", (kredit_id,))
db_restschuld = cursor.fetchone()[0]
print(f" Restschuld in Datenbank: {db_restschuld:.2f}")
print(f" Restschuld in Excel: {restschuld_aktuell:.2f}")
if abs(float(db_restschuld) - float(restschuld_aktuell)) < 0.01:
print(" ✓ Restschuld stimmt überein!")
else:
print(" ⚠ Restschuld weicht ab!")
return True
except Exception as e:
conn.rollback()
print(f"\n✗ FEHLER: {e}")
import traceback
traceback.print_exc()
return False
finally:
cursor.close()
conn.close()
if __name__ == '__main__':
success = import_niki_schulden()
exit(0 if success else 1)