215 lines
7.0 KiB
Python
215 lines
7.0 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
KORRIGIERTER IMPORT fuer "Schulden Niki.xlsx"
|
|
|
|
WICHTIG: Das ist eine FORDERUNG (eingehend) - Geld was Rene BEKOMMT!
|
|
- Richtung: 'eingehend'
|
|
- Restschuld STEIGT wenn Zahlung kommt (weil er mehr bekommt)
|
|
- Farbe: Grün (Einnahme)
|
|
"""
|
|
|
|
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 - KORRIGIERT fuer Forderungen"""
|
|
|
|
print("=" * 60)
|
|
print("IMPORT: Niki Schulden (KORRIGIERT)")
|
|
print("=" * 60)
|
|
print("\nHINWEIS: Das ist eine FORDERUNG (Geld was Rene BEKOMMT)")
|
|
print(" Richtung: eingehend (grün)")
|
|
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 (Forderung): {restschuld_start}")
|
|
|
|
monatsrate = get_monthly_rate(data)
|
|
print(f" Erkannte Monatsrate: {monatsrate}")
|
|
|
|
# 2. Kredit erstellen - ALS FORDERUNG (eingehend)
|
|
print("\n2. Erstelle Forderung (Kredit mit richtung=eingehend)...")
|
|
|
|
last_row = data[-1]
|
|
restschuld_aktuell = abs(last_row.get('Restschuld', 0))
|
|
|
|
kredit_data = {
|
|
'name': 'Niki Schulden (Forderung)',
|
|
'kreditgeber': 'Niki', # Niki ist der Schuldner
|
|
'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',
|
|
'richtung': 'eingehend' # WICHTIG: Das ist eine Forderung!
|
|
}
|
|
|
|
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 der Forderung")
|
|
return False
|
|
|
|
kredit_id = result.get('id')
|
|
print(f" [OK] Forderung erstellt mit ID: {kredit_id}")
|
|
|
|
# 3. Zahlungen importieren
|
|
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 = Zahlung die Niki an Rene macht -> Erhöht die Forderung
|
|
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': 'zahlung_eingang', # Niki zahlt -> Rene bekommt Geld
|
|
'notiz': fuer_was if fuer_was else 'Zahlung von Niki'
|
|
}
|
|
|
|
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 = Rene gibt Niki Geld -> Vermindert die Forderung
|
|
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', # Rene gibt Geld aus -> Forderung sinkt
|
|
'notiz': fuer_was if fuer_was else 'Neue 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" Restforderung in DB: {db_restschuld}")
|
|
print(f" Erwartet (aus Excel): {restschuld_aktuell}")
|
|
|
|
if abs(float(db_restschuld) - float(restschuld_aktuell)) < 0.01:
|
|
print(" [OK] Restforderung stimmt ueberein!")
|
|
else:
|
|
print(" [WARN] Restforderung weicht ab!")
|
|
|
|
print("\n" + "=" * 60)
|
|
print("IMPORT ABGESCHLOSSEN")
|
|
print("=" * 60)
|
|
print("\nHinweis: Diese Forderung wird als 'eingehend' markiert")
|
|
print(" und in der UI in GRUEN angezeigt.")
|
|
|
|
return True
|
|
|
|
if __name__ == '__main__':
|
|
success = import_niki_schulden()
|
|
exit(0 if success else 1)
|