219 lines
6.6 KiB
JavaScript
219 lines
6.6 KiB
JavaScript
#!/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);
|
|
});
|