// scripts/rebuild-timesheet-pdfs.js // Läuft im Projekt root: node scripts/rebuild-timesheet-pdfs.js // Erzeugt (bzw. speichert) fehlende PDFs für alle eingereichten weekly_timesheets, // basierend auf der bestehenden versionstreuen Generierungslogik. const path = require('path'); const { db } = require('../database'); const { generatePDFToBuffer } = require('../services/pdf-service'); const { resolvePdfLocationFromTimesheetRow, fileExists, savePdfBufferAtomic, } = require('../services/pdf-storage-service'); async function getAllSubmittedTimesheets() { const sql = ` SELECT wt.id, wt.user_id, wt.week_start, wt.week_end, wt.version, wt.pdf_path, u.firstname, u.lastname, u.username FROM weekly_timesheets wt JOIN users u ON u.id = wt.user_id WHERE wt.status = 'eingereicht' ORDER BY wt.week_start, wt.user_id, wt.version `; return new Promise((resolve, reject) => { db.all(sql, [], (err, rows) => { if (err) return reject(err); resolve(rows || []); }); }); } async function rebuildMissingPdfs() { const all = await getAllSubmittedTimesheets(); if (!all.length) { console.log('Keine eingereichten weekly_timesheets gefunden.'); return; } console.log(`Gefundene eingereichte weekly_timesheets: ${all.length}`); let processed = 0; let created = 0; let skippedExists = 0; let failed = 0; for (const row of all) { processed += 1; try { const loc = resolvePdfLocationFromTimesheetRow(row); const absolutePath = loc.absolutePath; const exists = await fileExists(absolutePath); if (exists) { skippedExists += 1; if (processed % 50 === 0) { console.log( `[${processed}/${all.length}] Timesheet #${row.id}: PDF existiert bereits -> übersprungen.`, ); } continue; } console.log( `[${processed}/${all.length}] Erzeuge PDF für Timesheet #${row.id} (User ${row.user_id}, KW: ${row.week_start}..${row.week_end}, Version ${row.version})`, ); // Mock-Request für generatePDFToBuffer – analog zu verwaltung-routes bulk-download const mockReq = { session: { userId: null, // hier optional eine system-User-ID einsetzen, wenn benötigt }, query: {}, }; const buffer = await generatePDFToBuffer(row.id, mockReq); await savePdfBufferAtomic(absolutePath, buffer); // Optional: pdf_path in DB setzen, falls noch leer if (!row.pdf_path) { const relativePath = loc.relativePath; await new Promise((resolve, reject) => { db.run( 'UPDATE weekly_timesheets SET pdf_path = ? WHERE id = ?', [relativePath, row.id], (err) => { if (err) return reject(err); resolve(); }, ); }); } created += 1; } catch (err) { failed += 1; console.error( `Fehler beim Erzeugen der PDF für Timesheet #${row.id}:`, err && err.message ? err.message : err, ); } } console.log('-----------------------------'); console.log('Rebuild abgeschlossen.'); console.log(`Gesamt: ${processed}`); console.log(`Neu erzeugt: ${created}`); console.log(`Bereits vorhanden: ${skippedExists}`); console.log(`Fehler: ${failed}`); } // Direktstart, wenn Datei via node aufgerufen wird if (require.main === module) { rebuildMissingPdfs() .then(() => { console.log('Fertig.'); // DB-Verbindung optional schließen, falls du willst: // db.close(); }) .catch((err) => { console.error('Unerwarteter Fehler beim Rebuild:', err); process.exitCode = 1; }); } module.exports = { rebuildMissingPdfs };