129 lines
3.7 KiB
JavaScript
129 lines
3.7 KiB
JavaScript
// 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 }; |