Initial commit - Stand 26.04.2026
This commit is contained in:
@@ -0,0 +1,274 @@
|
||||
/**
|
||||
* VOLLSTÄNDIGER NEU-IMPORT: Niki Kredit via API
|
||||
* Keine externen Abhängigkeiten - direkter HTTP-Call
|
||||
*/
|
||||
|
||||
const http = require('http');
|
||||
|
||||
const API_BASE = 'http://localhost:3001';
|
||||
|
||||
// EXTRahierte Daten aus der Excel-Analyse
|
||||
// Format: [datum, abgezahlt, neue_kosten, fuer_was]
|
||||
const EXCEL_DATA = [
|
||||
['2024-04-01', 500, null, null],
|
||||
['2024-05-01', 500, null, null],
|
||||
['2024-06-01', 150, 90, 'Kameras'],
|
||||
['2024-07-01', 450, 45, 'Kameras'],
|
||||
['2024-08-01', 500, null, null],
|
||||
['2024-09-01', 300, null, null],
|
||||
['2024-10-01', 300, 110, 'Videorekorder + Zubehör'],
|
||||
['2025-02-01', 200, null, null],
|
||||
['2025-06-01', 500, 260, 'Handyvertag']
|
||||
];
|
||||
|
||||
// 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('NIKI KREDIT - VOLLSTÄNDIGER NEU-IMPORT');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('SCHRITT 1: Alten Kredit "Niki" löschen');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// Alle Kredite holen
|
||||
let kredite;
|
||||
try {
|
||||
kredite = await apiCall('GET', '/kredite');
|
||||
} catch (err) {
|
||||
console.error('Fehler beim Abrufen der Kredite:', err.message);
|
||||
console.log('Stelle sicher, dass das Backend läuft (docker-compose up -d)');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const nikiKredite = kredite.filter(k => k.name?.toLowerCase().includes('niki'));
|
||||
|
||||
for (const kredit of nikiKredite) {
|
||||
console.log(`Lösche Kredit: ${kredit.name} (${kredit.id})`);
|
||||
try {
|
||||
await apiCall('DELETE', `/kredite/${kredit.id}`);
|
||||
console.log(' -> Gelöscht');
|
||||
} catch (err) {
|
||||
console.log(' -> Fehler beim Löschen:', err.message);
|
||||
}
|
||||
}
|
||||
|
||||
if (nikiKredite.length === 0) {
|
||||
console.log('Kein Kredit "Niki" gefunden');
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('SCHRITT 2: Excel-Daten verarbeiten');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// Extrahiere Zahlungen
|
||||
const zahlungen = [];
|
||||
|
||||
for (const row of EXCEL_DATA) {
|
||||
const [datum, abgezahlt, neueKosten, fuerWas] = row;
|
||||
|
||||
// Zahlung (Abgezahlt > 0)
|
||||
if (abgezahlt && abgezahlt > 0) {
|
||||
zahlungen.push({
|
||||
datum: datum,
|
||||
typ: 'zahlung',
|
||||
betrag: abgezahlt,
|
||||
notiz: fuerWas || 'Rate gezahlt'
|
||||
});
|
||||
}
|
||||
|
||||
// Neue Kosten (negative Auslage)
|
||||
if (neueKosten && neueKosten > 0) {
|
||||
zahlungen.push({
|
||||
datum: datum,
|
||||
typ: 'auslage',
|
||||
betrag: -neueKosten,
|
||||
notiz: fuerWas || 'Neue Kosten'
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
console.log(`Gefunden:`);
|
||||
console.log(`- ${zahlungen.filter(z => z.typ === 'zahlung').length} Zahlungen`);
|
||||
console.log(`- ${zahlungen.filter(z => z.typ === 'auslage').length} Auslagen`);
|
||||
console.log('\nAlle Transaktionen:');
|
||||
for (const z of zahlungen) {
|
||||
console.log(` ${z.datum} | ${z.typ.padEnd(10)} | ${z.betrag.toFixed(2).padStart(8)} € | ${z.notiz}`);
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('SCHRITT 3: Neuen Kredit anlegen');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
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 (Schulden Niki.xlsx)'
|
||||
};
|
||||
|
||||
console.log('Kredit-Daten:');
|
||||
console.log(` Name: ${kreditData.name}`);
|
||||
console.log(` Ursprungsschuld: ${kreditData.ursprungsschuld} €`);
|
||||
console.log(` Restschuld nach Import: ${kreditData.restschuld.toFixed(2)} €`);
|
||||
console.log(` Zinssatz: ${kreditData.zinssatz}%`);
|
||||
console.log(` Start: ${kreditData.start_datum}`);
|
||||
console.log(` Richtung: ${kreditData.richtung}`);
|
||||
console.log(` Summe Zahlungen: ${summeZahlungen.toFixed(2)} €`);
|
||||
console.log(` Summe Auslagen: ${summeAuslagen.toFixed(2)} €`);
|
||||
|
||||
let neuerKredit;
|
||||
try {
|
||||
neuerKredit = await apiCall('POST', '/kredite', kreditData);
|
||||
console.log(`\n✅ Kredit angelegt mit ID: ${neuerKredit.id}`);
|
||||
} catch (err) {
|
||||
console.error('\n❌ Fehler beim Anlegen des Kredits:', err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('SCHRITT 4: Zahlungen importieren');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
for (const z of zahlungen) {
|
||||
try {
|
||||
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}`);
|
||||
} catch (err) {
|
||||
console.log(` ❌ ${z.datum} | FEHLER: ${err.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('SCHRITT 5: Verifikation');
|
||||
console.log('='.repeat(60));
|
||||
|
||||
// Kredit prüfen
|
||||
let alleKredite;
|
||||
try {
|
||||
alleKredite = await apiCall('GET', '/kredite');
|
||||
} catch (err) {
|
||||
console.error('Fehler beim Abrufen:', err.message);
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
const nikiKredit = alleKredite.find(k => k.id === neuerKredit.id);
|
||||
|
||||
if (!nikiKredit) {
|
||||
console.log('❌ Kredit nicht gefunden!');
|
||||
process.exit(1);
|
||||
}
|
||||
|
||||
console.log('\nKredit in DB:');
|
||||
console.log(` ID: ${nikiKredit.id}`);
|
||||
console.log(` Name: ${nikiKredit.name}`);
|
||||
console.log(` Ursprungsschuld: ${parseFloat(nikiKredit.ursprungsschuld).toFixed(2)} €`);
|
||||
console.log(` Restschuld: ${parseFloat(nikiKredit.restschuld).toFixed(2)} €`);
|
||||
console.log(` Zinssatz: ${nikiKredit.zinssatz}%`);
|
||||
console.log(` Richtung: ${nikiKredit.richtung}`);
|
||||
|
||||
// Zahlungen prüfen
|
||||
let zahlungenDB;
|
||||
try {
|
||||
zahlungenDB = await apiCall('GET', `/kredite/${neuerKredit.id}/zahlungen`);
|
||||
} catch (err) {
|
||||
console.log('Zahlungen-Endpoint nicht verfügbar (kann normal sein)');
|
||||
zahlungenDB = [];
|
||||
}
|
||||
|
||||
console.log(`\nZahlungen in DB: ${zahlungenDB.length}`);
|
||||
|
||||
let sumZahlungenDB = 0;
|
||||
let sumAuslagenDB = 0;
|
||||
for (const z of zahlungenDB) {
|
||||
const betrag = parseFloat(z.betrag);
|
||||
const typ = z.typ || 'zahlung';
|
||||
console.log(` ${z.datum} | ${typ.padEnd(10)} | ${betrag.toFixed(2).padStart(8)} € | ${z.notizen || ''}`);
|
||||
if (typ === 'zahlung') sumZahlungenDB += betrag;
|
||||
if (typ === 'auslage') sumAuslagenDB += betrag;
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('SUMMEN-VERGLEICH');
|
||||
console.log('='.repeat(60));
|
||||
console.log(` Excel Zahlungen: ${summeZahlungen.toFixed(2).padStart(8)} €`);
|
||||
console.log(` DB Zahlungen: ${sumZahlungenDB.toFixed(2).padStart(8)} €`);
|
||||
console.log(` Excel Auslagen: ${summeAuslagen.toFixed(2).padStart(8)} €`);
|
||||
console.log(` DB Auslagen: ${sumAuslagenDB.toFixed(2).padStart(8)} €`);
|
||||
|
||||
const zahlungDiff = Math.abs(summeZahlungen - sumZahlungenDB);
|
||||
const auslageDiff = Math.abs(summeAuslagen - sumAuslagenDB);
|
||||
|
||||
if (zahlungDiff < 0.01 && auslageDiff < 0.01) {
|
||||
console.log('\n✅ VERIFIKATION ERFOLGREICH: Alle Daten stimmen überein!');
|
||||
console.log(` - ${zahlungenDB.length} Zahlungen korrekt importiert`);
|
||||
console.log(` - Restschuld korrekt berechnet`);
|
||||
console.log(` - Verlauf ist abrufbar`);
|
||||
} else {
|
||||
console.log('\n❌ WARNUNG: Unterschiede gefunden!');
|
||||
if (zahlungDiff >= 0.01) console.log(` Zahlungsdifferenz: ${zahlungDiff.toFixed(2)} €`);
|
||||
if (auslageDiff >= 0.01) console.log(` Auslagendifferenz: ${auslageDiff.toFixed(2)} €`);
|
||||
}
|
||||
|
||||
console.log('\n' + '='.repeat(60));
|
||||
console.log('IMPORT ABGESCHLOSSEN');
|
||||
console.log('='.repeat(60));
|
||||
console.log(`✅ Kredit 'Niki Schulden' ist jetzt korrekt in der Datenbank.`);
|
||||
console.log(`✅ Alle Zahlungen und Auslagen sind importiert.`);
|
||||
console.log(`✅ Kann als Template für Kerstin verwendet werden.`);
|
||||
}
|
||||
|
||||
main().catch(err => {
|
||||
console.error('Fehler:', err);
|
||||
process.exit(1);
|
||||
});
|
||||
Reference in New Issue
Block a user