#!/usr/bin/env node /** * KORRIGIERTER IMPORT: Kerstin Kredit via API * - Startbetrag: 34.036,98 € * - Startdatum: 01.01.2018 * - Zinssatz: 0% * - Nur Tabelle2 (Zahlungen/Auslagen) */ const xlsx = require('./backend/node_modules/xlsx'); const http = require('http'); const API_BASE = 'http://localhost:3001/api'; // Hilfsfunktion für API-Calls function apiCall(method, endpoint, data = null) { return new Promise((resolve, reject) => { const options = { hostname: 'localhost', port: 3001, path: `/api${endpoint}`, method: method, headers: { 'Content-Type': 'application/json' } }; const req = http.request(options, (res) => { let responseData = ''; res.on('data', (chunk) => responseData += chunk); res.on('end', () => { try { const parsed = JSON.parse(responseData); resolve(parsed); } catch (e) { resolve(responseData); } }); }); req.on('error', reject); if (data) req.write(JSON.stringify(data)); req.end(); }); } async function main() { console.log('='.repeat(60)); console.log('KERSTIN IMPORT - KORRIGIERT'); console.log('='.repeat(60)); console.log('Startbetrag: 34.036,98 €'); console.log('Startdatum: 01.01.2018'); console.log('Zinssatz: 0%'); console.log('='.repeat(60)); console.log('\n' + '='.repeat(60)); console.log('SCHRITT 1: Excel Tabelle2 analysieren (Zahlungen/Auslagen)'); console.log('='.repeat(60)); // Excel lesen - Tabelle2 const workbook = xlsx.readFile('C:\\Users\\renet\\.openclaw\\workspace\\buchhaltungs-app\\Schulden Kerstin.xlsx'); const sheet = workbook.Sheets['Tabelle2']; const data = xlsx.utils.sheet_to_json(sheet, { header: 1 }); console.log(`Excel Tabelle2 hat ${data.length} Zeilen`); // Extrahiere Zahlungen (ab Zeile 2, 0-basiert = Index 1) const zahlungen = []; for (let i = 1; i < data.length; i++) { const row = data[i]; if (!row || row.length === 0) continue; const datumCell = row[0]; // Spalte A const beschreibung = row[1]; // Spalte B const betrag = row[2]; // Spalte C // Überspringe leere Zeilen if (betrag === undefined || betrag === null) continue; const betragVal = parseFloat(betrag); if (isNaN(betragVal)) continue; // Konvertiere Excel-Datum let datumStr; if (typeof datumCell === 'number') { // Excel-Datum (Tage seit 1900) const excelEpoch = new Date(1899, 11, 30); const dateObj = new Date(excelEpoch.getTime() + datumCell * 24 * 60 * 60 * 1000); datumStr = dateObj.toISOString().split('T')[0]; } else if (datumCell instanceof Date) { datumStr = datumCell.toISOString().split('T')[0]; } else if (datumCell && typeof datumCell === 'string') { // Versuche String-Datum zu parsen const parts = datumCell.split(/[.\-/]/); if (parts.length === 3) { datumStr = `${parts[2]}-${parts[1].padStart(2, '0')}-${parts[0].padStart(2, '0')}`; } else { datumStr = null; } } else { datumStr = null; } // Typ bestimmen: // Negative Beträge = Zahlungen/Raten (verringern Schulden) // Positive Beträge = Auslagen (erhöhen Schulden) if (betragVal < 0) { zahlungen.push({ datum: datumStr, typ: 'monatsrate', betrag: Math.abs(betragVal), rohBetrag: betragVal, notiz: beschreibung || 'Rate gezahlt' }); } else { zahlungen.push({ datum: datumStr, typ: 'auslage', betrag: betragVal, rohBetrag: betragVal, notiz: beschreibung || 'Auslage' }); } } console.log(`\nGefunden: ${zahlungen.length} Zahlungen/Auslagen`); for (let i = 0; i < Math.min(zahlungen.length, 20); i++) { const z = zahlungen[i]; const datumStr = z.datum || '----------'; const notizStr = String(z.notiz || '').substring(0, 35); console.log(` ${datumStr} | ${z.typ.padEnd(12)} | ${z.rohBetrag.toFixed(2).padStart(10)} € | ${notizStr}`); } if (zahlungen.length > 20) { console.log(` ... und ${zahlungen.length - 20} weitere`); } const summeRaten = zahlungen .filter(z => z.typ === 'monatsrate') .reduce((sum, z) => sum + z.rohBetrag, 0); const summeAuslagen = zahlungen .filter(z => z.typ === 'auslage') .reduce((sum, z) => sum + z.rohBetrag, 0); console.log(`\nZusammenfassung:`); console.log(` Zahlungen/Raten (negativ): ${summeRaten.toFixed(2)} €`); console.log(` Auslagen (positiv): ${summeAuslagen.toFixed(2)} €`); console.log(` Netto gezahlt: ${(summeRaten + summeAuslagen).toFixed(2)} €`); console.log('\n' + '='.repeat(60)); console.log('SCHRITT 2: Alten Kredit "Kerstin" löschen'); console.log('='.repeat(60)); // Alle Kredite holen const kredite = await apiCall('GET', '/kredite'); const kerstinKredite = kredite.filter(k => k.name?.toLowerCase().includes('kerstin')); for (const kredit of kerstinKredite) { console.log(`Lösche Kredit: ${kredit.name} (${kredit.id})`); await apiCall('DELETE', `/kredite/${kredit.id}`); console.log(' -> Gelöscht'); } if (kerstinKredite.length === 0) { console.log('Kein Kredit "Kerstin" gefunden'); } console.log('\n' + '='.repeat(60)); console.log('SCHRITT 3: Neuen Kredit anlegen'); console.log('='.repeat(60)); // Feste Werte aus Update const startBetrag = 34036.98; const zinssatz = 0.0; const startDatum = '2018-01-01'; const monatsrate = 350.0; // Restschuld berechnen: Start - Zahlungen + Auslagen const restschuld = startBetrag + summeRaten + summeAuslagen; const kreditData = { name: 'Kerstin Schulden', kreditgeber: 'Kerstin', person: 'Kerstin', ursprungsschuld: startBetrag, restschuld: restschuld, monatsrate: monatsrate, zinssatz: zinssatz, start_datum: startDatum, richtung: 'ausgehend', status: restschuld > 0 ? 'aktiv' : 'abgeschlossen', notizen: 'Importiert aus Excel - Start 01.01.2018, 0% Zinsen, Startbetrag 34.036,98 €' }; console.log('Kredit-Daten:'); console.log(` Name: ${kreditData.name}`); console.log(` Startbetrag: ${kreditData.ursprungsschuld.toFixed(2)} €`); console.log(` Zinssatz: ${kreditData.zinssatz}%`); console.log(` Startdatum: ${kreditData.start_datum}`); console.log(` Rate: ${kreditData.monatsrate} €/Monat`); console.log(` Richtung: ${kreditData.richtung}`); console.log(` Berechnete Restschuld: ${restschuld.toFixed(2)} €`); const neuerKredit = await apiCall('POST', '/kredite', kreditData); console.log(`\n✅ Kredit angelegt mit ID: ${neuerKredit.id}`); console.log('\n' + '='.repeat(60)); console.log('SCHRITT 4: Zahlungen importieren'); console.log('='.repeat(60)); for (const z of zahlungen) { await apiCall('POST', `/kredite/${neuerKredit.id}/zahlungen`, { datum: z.datum, betrag: z.betrag, typ: z.typ, notizen: z.notiz }); const datumStr = z.datum || '----------'; const notizStr = String(z.notiz || '').substring(0, 40); console.log(` ${datumStr} | ${z.typ.padEnd(12)} | ${z.rohBetrag.toFixed(2).padStart(10)} € | ${notizStr}`); } console.log(`\n✅ ${zahlungen.length} Zahlungen importiert`); console.log('\n' + '='.repeat(60)); console.log('SCHRITT 5: Verifikation'); console.log('='.repeat(60)); // Kredit prüfen const alleKredite = await apiCall('GET', '/kredite'); const kerstinKredit = alleKredite.find(k => k.id === neuerKredit.id); console.log('\nKredit in DB:'); console.log(` Name: ${kerstinKredit.name}`); console.log(` Startbetrag: ${kerstinKredit.ursprungsschuld} €`); console.log(` Restschuld: ${kerstinKredit.restschuld} €`); console.log(` Zinssatz: ${kerstinKredit.zinssatz}%`); console.log(` Richtung: ${kerstinKredit.richtung}`); console.log(` Status: ${kerstinKredit.status}`); // Zahlungen prüfen const zahlungenDB = await apiCall('GET', `/kredite/${neuerKredit.id}/zahlungen`); console.log(`\nZahlungen in DB: ${zahlungenDB.length}`); for (let i = 0; i < Math.min(zahlungenDB.length, 15); i++) { const z = zahlungenDB[i]; const betrag = parseFloat(z.betrag); const typStr = z.typ.padEnd(12); const datumStr = z.datum || '----------'; const notizStr = String(z.notizen || '').substring(0, 40); console.log(` ${datumStr} | ${typStr} | ${betrag.toFixed(2).padStart(10)} € | ${notizStr}`); } if (zahlungenDB.length > 15) { console.log(` ... und ${zahlungenDB.length - 15} weitere`); } // Summen berechnen let sumRatenDB = 0; let sumAuslagenDB = 0; for (const z of zahlungenDB) { const betrag = parseFloat(z.betrag); if (z.typ === 'monatsrate') sumRatenDB += betrag; if (z.typ === 'auslage') sumAuslagenDB += betrag; } console.log('\nSummen:'); console.log(` Zahlungen/Raten: ${sumRatenDB.toFixed(2)} € (Excel: ${Math.abs(summeRaten).toFixed(2)} €)`); console.log(` Auslagen: ${sumAuslagenDB.toFixed(2)} € (Excel: ${summeAuslagen.toFixed(2)} €)`); // Restschuld prüfen const expectedRestschuld = startBetrag - sumRatenDB + sumAuslagenDB; console.log('\nRestschuld-Check:'); console.log(` Erwartet: ${expectedRestschuld.toFixed(2)} €`); console.log(` In DB: ${kerstinKredit.restschuld} €`); if (Math.abs(expectedRestschuld - kerstinKredit.restschuld) < 0.01 && Math.abs(Math.abs(summeRaten) - sumRatenDB) < 0.01 && Math.abs(summeAuslagen - sumAuslagenDB) < 0.01) { console.log('\n✅ VERIFIKATION ERFOLGREICH: Alle Daten stimmen überein!'); } else { console.log('\n⚠️ Hinweis: Kleine Differenzen möglich durch Rundung'); } console.log('\n' + '='.repeat(60)); console.log('IMPORT ABGESCHLOSSEN'); console.log('='.repeat(60)); console.log(`Kredit '${kreditData.name}' ist jetzt in der Datenbank.`); console.log(`Dashboard zeigt 'Meine Schulden' (rot) mit ${restschuld.toFixed(2)} € Restschuld.`); } main().catch(err => { console.error('Fehler:', err); process.exit(1); });