#!/usr/bin/env node /** * VOLLSTÄNDIGER NEU-IMPORT: Niki Kredit via API */ const xlsx = require('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('SCHRITT 1: Excel analysieren'); console.log('='.repeat(60)); // Excel lesen const workbook = xlsx.readFile('Schulden Niki.xlsx'); const sheet = workbook.Sheets['Tabelle1']; const data = xlsx.utils.sheet_to_json(sheet, { header: 1 }); console.log(`Excel hat ${data.length} Zeilen`); console.log(`Header in Zeile 6: ${data[5]?.slice(2, 8)}`); // Extrahiere Zahlungen (ab Zeile 7, 0-basiert = Index 6) const zahlungen = []; for (let i = 6; i < data.length; i++) { const row = data[i]; if (!row || !row[2]) continue; const datum = row[2]; const abgezahlt = row[5]; const neueKosten = row[6]; const fuerWas = row[7]; // Konvertiere Excel-Datum let datumStr; if (typeof datum === 'number') { // Excel-Datum (Tage seit 1900) const excelEpoch = new Date(1899, 11, 30); const dateObj = new Date(excelEpoch.getTime() + datum * 24 * 60 * 60 * 1000); datumStr = dateObj.toISOString().split('T')[0]; } else if (datum instanceof Date) { datumStr = datum.toISOString().split('T')[0]; } else { datumStr = String(datum).split(' ')[0]; } // Zahlung (Abgezahlt > 0) if (abgezahlt && parseFloat(abgezahlt) > 0) { zahlungen.push({ datum: datumStr, typ: 'zahlung', betrag: parseFloat(abgezahlt), notiz: fuerWas || 'Rate gezahlt' }); } // Neue Kosten (negative Auslage) if (neueKosten && parseFloat(neueKosten) > 0) { zahlungen.push({ datum: datumStr, typ: 'auslage', betrag: -parseFloat(neueKosten), notiz: fuerWas || 'Neue Kosten' }); } } console.log(`\nGefunden:`); console.log(`- ${zahlungen.filter(z => z.typ === 'zahlung').length} Zahlungen`); console.log(`- ${zahlungen.filter(z => z.typ === 'auslage').length} Auslagen`); console.log('\n' + '='.repeat(60)); console.log('SCHRITT 2: Alten Kredit "Niki" löschen'); console.log('='.repeat(60)); // Alle Kredite holen const kredite = await apiCall('GET', '/kredite'); const nikiKredite = kredite.filter(k => k.name?.toLowerCase().includes('niki')); for (const kredit of nikiKredite) { console.log(`Lösche Kredit: ${kredit.name} (${kredit.id})`); await apiCall('DELETE', `/kredite/${kredit.id}`); console.log(' -> Gelöscht'); } if (nikiKredite.length === 0) { console.log('Kein Kredit "Niki" gefunden'); } console.log('\n' + '='.repeat(60)); console.log('SCHRITT 3: Neuen Kredit anlegen'); console.log('='.repeat(60)); const summeZahlungen = zahlungen .filter(z => z.typ === 'zahlung') .reduce((sum, z) => sum + z.betrag, 0); const summeAuslagen = zahlungen .filter(z => z.typ === 'auslage') .reduce((sum, z) => sum + z.betrag, 0); const kreditData = { name: 'Niki Schulden', kreditgeber: 'Niki', person: 'Niki', ursprungsschuld: 7000, restschuld: 7000 - summeZahlungen + Math.abs(summeAuslagen), monatsrate: 500, zinssatz: 10, start_datum: '2023-07-01', richtung: 'eingehend', status: 'aktiv', notizen: 'Importiert aus Excel' }; console.log('Kredit-Daten:'); console.log(` Name: ${kreditData.name}`); console.log(` Ursprungsschuld: ${kreditData.ursprungsschuld} €`); console.log(` Zinssatz: ${kreditData.zinssatz}%`); console.log(` Summe Zahlungen: ${summeZahlungen} €`); console.log(` Summe Auslagen: ${summeAuslagen} €`); const neuerKredit = await apiCall('POST', '/kredite', kreditData); console.log(`\nKredit 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 }); console.log(` ${z.datum} | ${z.typ.padEnd(10)} | ${z.betrag.toFixed(2).padStart(8)} € | ${z.notiz}`); } console.log('\n' + '='.repeat(60)); console.log('SCHRITT 5: Verifikation'); console.log('='.repeat(60)); // Kredit prüfen const alleKredite = await apiCall('GET', '/kredite'); const nikiKredit = alleKredite.find(k => k.id === neuerKredit.id); console.log('\nKredit in DB:'); console.log(` Name: ${nikiKredit.name}`); console.log(` Ursprungsschuld: ${nikiKredit.ursprungsschuld} €`); console.log(` Restschuld: ${nikiKredit.restschuld} €`); console.log(` Richtung: ${nikiKredit.richtung}`); // Zahlungen prüfen const zahlungenDB = await apiCall('GET', `/kredite/${neuerKredit.id}/zahlungen`); console.log(`\nZahlungen in DB: ${zahlungenDB.length}`); let sumZahlungenDB = 0; let sumAuslagenDB = 0; for (const z of zahlungenDB) { const betrag = parseFloat(z.betrag); console.log(` ${z.datum} | ${z.typ.padEnd(10)} | ${betrag.toFixed(2).padStart(8)} € | ${z.notizen}`); if (z.typ === 'zahlung') sumZahlungenDB += betrag; if (z.typ === 'auslage') sumAuslagenDB += betrag; } console.log('\nSummen:'); console.log(` Zahlungen: ${sumZahlungenDB.toFixed(2)} € (Excel: ${summeZahlungen.toFixed(2)} €)`); console.log(` Auslagen: ${sumAuslagenDB.toFixed(2)} € (Excel: ${summeAuslagen.toFixed(2)} €)`); if (Math.abs(summeZahlungen - sumZahlungenDB) < 0.01 && Math.abs(summeAuslagen - sumAuslagenDB) < 0.01) { console.log('\n✅ VERIFIKATION ERFOLGREICH: Alle Daten stimmen überein!'); } else { console.log('\n❌ WARNUNG: Unterschiede gefunden!'); } console.log('\n' + '='.repeat(60)); console.log('IMPORT ABGESCHLOSSEN'); console.log('='.repeat(60)); } main().catch(err => { console.error('Fehler:', err); process.exit(1); });