287 lines
8.7 KiB
Python
287 lines
8.7 KiB
Python
#!/usr/bin/env python3
|
|
"""
|
|
KERSTIN KREDIT IMPORT - FINAL v3
|
|
Importiert ALLE Eintraege aus Tabelle2 (auch ohne explizites Datum)
|
|
"""
|
|
|
|
import psycopg2
|
|
import pandas as pd
|
|
from datetime import datetime
|
|
import re
|
|
|
|
print("="*60)
|
|
print("KERSTIN IMPORT - FINAL v3")
|
|
print("="*60)
|
|
print("Startbetrag: 34.036,98 EUR")
|
|
print("Startdatum: 01.01.2018")
|
|
print("Zinssatz: 0%")
|
|
print("="*60)
|
|
|
|
# Verbindung zur PostgreSQL in Docker
|
|
conn = psycopg2.connect(
|
|
host="localhost",
|
|
port=5432,
|
|
database="buchhaltung",
|
|
user="postgres",
|
|
password="postgres"
|
|
)
|
|
cursor = conn.cursor()
|
|
|
|
print("\n" + "="*60)
|
|
print("SCHRITT 1: Alten Kredit 'Kerstin' loeschen")
|
|
print("="*60)
|
|
|
|
cursor.execute("SELECT id, name FROM kredite WHERE name ILIKE '%kerstin%'")
|
|
kerstin_kredite = cursor.fetchall()
|
|
|
|
for kredit_id, name in kerstin_kredite:
|
|
print(f"Loesche Kredit: {name} (ID: {kredit_id})")
|
|
cursor.execute("DELETE FROM kredit_zahlungen WHERE kredit_id = %s", (kredit_id,))
|
|
cursor.execute("DELETE FROM kredit_buchungen WHERE kredit_id = %s", (kredit_id,))
|
|
cursor.execute("DELETE FROM kredite WHERE id = %s", (kredit_id,))
|
|
print(f" -> Geloescht")
|
|
|
|
if not kerstin_kredite:
|
|
print("Kein Kredit 'Kerstin' gefunden")
|
|
|
|
conn.commit()
|
|
|
|
print("\n" + "="*60)
|
|
print("SCHRITT 2: Excel Tabelle2 laden (Zahlungen/Auslagen)")
|
|
print("="*60)
|
|
|
|
# Excel-Datei lesen - Tabelle2
|
|
df = pd.read_excel('Schulden Kerstin.xlsx', sheet_name='Tabelle2', header=0)
|
|
|
|
print(f"Excel Tabelle2 hat {len(df)} Zeilen")
|
|
print(f"Spalten: {df.columns.tolist()}")
|
|
|
|
# Extrahiere ALLE gueltigen Eintraege (mit Betrag)
|
|
zahlungen = []
|
|
uebersprungen = 0
|
|
|
|
for idx, row in df.iterrows():
|
|
datum_raw = row.iloc[0] if len(row) > 0 else None
|
|
beschreibung = row.iloc[1] if len(row) > 1 else None
|
|
betrag = row.iloc[2] if len(row) > 2 else None
|
|
|
|
# Ueberspringe leere Zeilen
|
|
if pd.isna(betrag):
|
|
uebersprungen += 1
|
|
continue
|
|
|
|
try:
|
|
betrag_val = float(betrag)
|
|
except:
|
|
uebersprungen += 1
|
|
continue
|
|
|
|
# Ueberspringe Summenzeilen ("Gesammtbetrag" etc.)
|
|
if isinstance(datum_raw, str) and 'gesammt' in datum_raw.lower():
|
|
uebersprungen += 1
|
|
continue
|
|
|
|
# Datum konvertieren
|
|
datum_str = None
|
|
if isinstance(datum_raw, pd.Timestamp):
|
|
datum_str = datum_raw.strftime('%Y-%m-%d')
|
|
elif isinstance(datum_raw, datetime):
|
|
datum_str = datum_raw.strftime('%Y-%m-%d')
|
|
elif isinstance(datum_raw, str):
|
|
datum_clean = datum_raw.strip()
|
|
# Format: DD.MM.YYYY
|
|
parts = datum_clean.split('.')
|
|
if len(parts) == 3:
|
|
try:
|
|
day, month, year = parts
|
|
datum_str = f"{year}-{month.zfill(2)}-{day.zfill(2)}"
|
|
except:
|
|
datum_str = None
|
|
elif len(datum_clean) >= 10 and datum_clean[4] == '-':
|
|
datum_str = datum_clean[:10]
|
|
|
|
# Beschreibung extrahieren
|
|
notiz = str(beschreibung) if not pd.isna(beschreibung) else ""
|
|
if not notiz or notiz == "nan":
|
|
notiz = "Auslage" if betrag_val > 0 else "Rate gezahlt"
|
|
|
|
# Typ bestimmen
|
|
if betrag_val < 0:
|
|
zahlungen.append({
|
|
'datum': datum_str,
|
|
'typ': 'monatsrate',
|
|
'betrag': abs(betrag_val),
|
|
'roh_betrag': betrag_val,
|
|
'notiz': notiz
|
|
})
|
|
else:
|
|
zahlungen.append({
|
|
'datum': datum_str,
|
|
'typ': 'auslage',
|
|
'betrag': betrag_val,
|
|
'roh_betrag': betrag_val,
|
|
'notiz': notiz
|
|
})
|
|
|
|
print(f"\nGefunden: {len(zahlungen)} Zahlungen/Auslagen")
|
|
print(f"Uebersprungen: {uebersprungen} Eintraege (leer oder Summenzeilen)")
|
|
|
|
print(f"\nErste 20 Eintraege:")
|
|
for i, z in enumerate(zahlungen[:20]):
|
|
datum_disp = z['datum'] if z['datum'] else '----------'
|
|
print(f" {datum_disp} | {z['typ']:12} | {z['roh_betrag']:10.2f} EUR | {z['notiz'][:35]}")
|
|
|
|
if len(zahlungen) > 20:
|
|
print(f" ... und {len(zahlungen)-20} weitere")
|
|
|
|
summe_raten = sum(z['roh_betrag'] for z in zahlungen if z['typ'] == 'monatsrate')
|
|
summe_auslagen = sum(z['roh_betrag'] for z in zahlungen if z['typ'] == 'auslage')
|
|
|
|
print(f"\nZusammenfassung:")
|
|
print(f" Zahlungen/Raten (negativ): {summe_raten:.2f} EUR")
|
|
print(f" Auslagen (positiv): {summe_auslagen:.2f} EUR")
|
|
print(f" Netto gezahlt: {summe_raten + summe_auslagen:.2f} EUR")
|
|
|
|
print("\n" + "="*60)
|
|
print("SCHRITT 3: Kredit anlegen")
|
|
print("="*60)
|
|
|
|
# Feste Werte aus Update
|
|
kredit_name = "Kerstin Schulden"
|
|
start_betrag = 34036.98
|
|
zinssatz = 0.0
|
|
start_datum = '2018-01-01'
|
|
monatsrate = 350.0
|
|
richtung = 'ausgehend'
|
|
|
|
# Restschuld berechnen: Start + Raten (negativ) + Auslagen (positiv)
|
|
restschuld = start_betrag + summe_raten + summe_auslagen
|
|
|
|
print(f"Kredit: {kredit_name}")
|
|
print(f" Startbetrag: {start_betrag:.2f} EUR")
|
|
print(f" Zinssatz: {zinssatz}%")
|
|
print(f" Start: {start_datum}")
|
|
print(f" Rate: {monatsrate} EUR/Monat")
|
|
print(f" Richtung: {richtung}")
|
|
print(f" Berechnete Restschuld: {restschuld:.2f} EUR")
|
|
|
|
cursor.execute("""
|
|
INSERT INTO kredite (name, kreditgeber, person, ursprungsschuld, restschuld,
|
|
monatsrate, zinssatz, start_datum, notizen, richtung, status)
|
|
VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
|
|
RETURNING id
|
|
""", (
|
|
kredit_name,
|
|
"Kerstin",
|
|
"Kerstin",
|
|
start_betrag,
|
|
restschuld,
|
|
monatsrate,
|
|
zinssatz,
|
|
start_datum,
|
|
"Importiert aus Excel - Start 01.01.2018, 0% Zinsen, Startbetrag 34.036,98 EUR",
|
|
richtung,
|
|
"aktiv" if restschuld > 0 else "abgeschlossen"
|
|
))
|
|
|
|
kredit_id = cursor.fetchone()[0]
|
|
conn.commit()
|
|
print(f"\n[OK] Kredit angelegt mit ID: {kredit_id}")
|
|
|
|
print("\n" + "="*60)
|
|
print("SCHRITT 4: Zahlungen importieren")
|
|
print("="*60)
|
|
|
|
imported_count = 0
|
|
imported_with_date = 0
|
|
imported_without_date = 0
|
|
|
|
for z in zahlungen:
|
|
# Wenn kein Datum, verwende Startdatum (01.01.2018)
|
|
datum_for_db = z['datum'] if z['datum'] else start_datum
|
|
|
|
cursor.execute("""
|
|
INSERT INTO kredit_zahlungen (kredit_id, datum, betrag, typ, notiz)
|
|
VALUES (%s, %s, %s, %s, %s)
|
|
""", (
|
|
kredit_id,
|
|
datum_for_db,
|
|
z['betrag'],
|
|
z['typ'],
|
|
z['notiz'][:200] if z['notiz'] else ""
|
|
))
|
|
imported_count += 1
|
|
if z['datum']:
|
|
imported_with_date += 1
|
|
else:
|
|
imported_without_date += 1
|
|
|
|
datum_disp = z['datum'] if z['datum'] else f"[{start_datum}]"
|
|
print(f" {datum_disp} | {z['typ']:12} | {z['roh_betrag']:10.2f} EUR | {z['notiz'][:40]}")
|
|
|
|
conn.commit()
|
|
print(f"\n[OK] {imported_count} Zahlungen importiert")
|
|
print(f" {imported_with_date} mit Datum, {imported_without_date} ohne Datum (Startdatum verwendet)")
|
|
|
|
print("\n" + "="*60)
|
|
print("SCHRITT 5: Verifikation")
|
|
print("="*60)
|
|
|
|
cursor.execute("SELECT * FROM kredite WHERE id = %s", (kredit_id,))
|
|
kredit = cursor.fetchone()
|
|
print(f"\nKredit in DB:")
|
|
print(f" Name: {kredit[1]}")
|
|
print(f" Startbetrag: {float(kredit[4]):.2f} EUR")
|
|
print(f" Restschuld: {float(kredit[5]):.2f} EUR")
|
|
print(f" Zinssatz: {float(kredit[7]):.2f}%")
|
|
print(f" Richtung: {kredit[12]}")
|
|
print(f" Status: {kredit[13]}")
|
|
|
|
cursor.execute("SELECT datum, betrag, typ, notiz FROM kredit_zahlungen WHERE kredit_id = %s ORDER BY datum", (kredit_id,))
|
|
imported_zahlungen = cursor.fetchall()
|
|
print(f"\nZahlungen in DB: {len(imported_zahlungen)}")
|
|
|
|
for i, z in enumerate(imported_zahlungen[:15]):
|
|
datum_str = str(z[0]) if z[0] else '----------'
|
|
betrag = float(z[1]) if z[1] else 0.0
|
|
typ = z[2]
|
|
notiz = str(z[3])[:40] if z[3] else ''
|
|
print(f" {datum_str} | {typ:12} | {betrag:10.2f} EUR | {notiz}")
|
|
|
|
if len(imported_zahlungen) > 15:
|
|
print(f" ... und {len(imported_zahlungen)-15} weitere")
|
|
|
|
cursor.execute("""
|
|
SELECT
|
|
COALESCE(SUM(CASE WHEN typ = 'monatsrate' THEN betrag ELSE 0 END), 0) as sum_raten,
|
|
COALESCE(SUM(CASE WHEN typ = 'auslage' THEN betrag ELSE 0 END), 0) as sum_auslagen
|
|
FROM kredit_zahlungen
|
|
WHERE kredit_id = %s
|
|
""", (kredit_id,))
|
|
result = cursor.fetchone()
|
|
sum_raten_db = float(result[0])
|
|
sum_auslagen_db = float(result[1])
|
|
|
|
print(f"\nSummen:")
|
|
print(f" Zahlungen/Raten: {sum_raten_db:.2f} EUR (Excel: {abs(summe_raten):.2f} EUR)")
|
|
print(f" Auslagen: {sum_auslagen_db:.2f} EUR (Excel: {summe_auslagen:.2f} EUR)")
|
|
|
|
expected_restschuld = start_betrag - sum_raten_db + sum_auslagen_db
|
|
print(f"\nRestschuld-Check:")
|
|
print(f" Erwartet: {expected_restschuld:.2f} EUR")
|
|
print(f" In DB: {float(kredit[5]):.2f} EUR")
|
|
|
|
if abs(expected_restschuld - float(kredit[5])) < 0.01:
|
|
print(f"\n[OK] VERIFIKATION ERFOLGREICH!")
|
|
else:
|
|
print(f"\n[Hinweis] Differenzen erkannt")
|
|
|
|
cursor.close()
|
|
conn.close()
|
|
|
|
print("\n" + "="*60)
|
|
print("IMPORT ABGESCHLOSSEN")
|
|
print("="*60)
|
|
print(f"Kredit '{kredit_name}' ist jetzt in der Datenbank.")
|
|
print(f"Dashboard zeigt 'Meine Schulden' (rot) mit {restschuld:.2f} EUR Restschuld.")
|