Sortieungsoptionen in Verwaltung, Umstellung der PDF generation auf generierung bei abgabe und ablage auf dem Sateisystem um einen Festen Stand zu garantieren
This commit is contained in:
@@ -2,9 +2,16 @@
|
||||
|
||||
const { db } = require('../database');
|
||||
const { requireAuth, requireVerwaltung } = require('../middleware/auth');
|
||||
const { generatePDF } = require('../services/pdf-service');
|
||||
const { generatePDFToBuffer } = require('../services/pdf-service');
|
||||
const { getHolidaysForDateRange } = require('../services/feiertage-service');
|
||||
const { hasRole } = require('../helpers/utils');
|
||||
const fs = require('fs');
|
||||
const {
|
||||
fileExists,
|
||||
savePdfBufferAtomic,
|
||||
resolvePdfLocationFromTimesheetRow,
|
||||
resolveAbsolutePathFromRelative,
|
||||
} = require('../services/pdf-storage-service');
|
||||
|
||||
/** Plausibilitätsprüfung Projektnummer: 7 Ziffern, beginnt mit 5, dann YY (Jahr), dann 4 freie Ziffern (z.B. 5260001). */
|
||||
function isValidProjectNumber(value) {
|
||||
@@ -553,18 +560,90 @@ function registerTimesheetRoutes(app) {
|
||||
const isVerwaltung = hasRole(req, 'verwaltung') || hasRole(req, 'admin');
|
||||
|
||||
// Prüfe ob User Verwaltung/Admin ist oder ob das Timesheet dem User gehört
|
||||
db.get(`SELECT user_id FROM weekly_timesheets WHERE id = ?`, [timesheetId], (err, timesheet) => {
|
||||
if (err || !timesheet) {
|
||||
return res.status(404).send('Stundenzettel nicht gefunden');
|
||||
db.get(
|
||||
`SELECT wt.id, wt.user_id, wt.week_start, wt.week_end, wt.version, wt.submitted_at, wt.pdf_path,
|
||||
u.firstname, u.lastname
|
||||
FROM weekly_timesheets wt
|
||||
JOIN users u ON wt.user_id = u.id
|
||||
WHERE wt.id = ?`,
|
||||
[timesheetId],
|
||||
async (err, timesheet) => {
|
||||
if (err || !timesheet) {
|
||||
return res.status(404).send('Stundenzettel nicht gefunden');
|
||||
}
|
||||
|
||||
// Zugriff erlauben wenn Verwaltung/Admin ODER wenn Timesheet dem User gehört
|
||||
if (!(isVerwaltung || timesheet.user_id === userId)) {
|
||||
return res.status(403).send('Zugriff verweigert');
|
||||
}
|
||||
|
||||
const inline = req.query.inline === 'true';
|
||||
|
||||
// Zielpfad bestimmen: DB-Pfad bevorzugen, sonst berechnen
|
||||
const computedLocation = resolvePdfLocationFromTimesheetRow(timesheet);
|
||||
const relativePath = timesheet.pdf_path ? String(timesheet.pdf_path) : computedLocation.relativePath;
|
||||
const absolutePath = timesheet.pdf_path ? resolveAbsolutePathFromRelative(relativePath) : computedLocation.absolutePath;
|
||||
const filename = computedLocation.filename;
|
||||
|
||||
res.setHeader('Content-Type', 'application/pdf');
|
||||
res.setHeader('X-Content-Type-Options', 'nosniff');
|
||||
if (inline) {
|
||||
res.setHeader('Content-Disposition', `inline; filename="${filename}"`);
|
||||
res.setHeader('X-Frame-Options', 'SAMEORIGIN');
|
||||
} else {
|
||||
res.setHeader('Content-Disposition', `attachment; filename="${filename}"`);
|
||||
|
||||
// Marker setzen, dass PDF heruntergeladen wurde (nur bei Download, nicht bei Vorschau)
|
||||
const downloadedBy = req.session.userId;
|
||||
if (downloadedBy) {
|
||||
db.run(
|
||||
`UPDATE weekly_timesheets
|
||||
SET pdf_downloaded_at = CURRENT_TIMESTAMP,
|
||||
pdf_downloaded_by = ?
|
||||
WHERE id = ?`,
|
||||
[downloadedBy, timesheetId],
|
||||
(updateErr) => {
|
||||
if (updateErr) {
|
||||
console.error('Fehler beim Setzen des Download-Markers:', updateErr);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
const exists = await fileExists(absolutePath);
|
||||
if (exists) {
|
||||
const stream = fs.createReadStream(absolutePath);
|
||||
stream.on('error', (streamErr) => {
|
||||
console.error('Fehler beim Lesen der PDF-Datei:', streamErr);
|
||||
if (!res.headersSent) res.status(500);
|
||||
res.end('Fehler beim Lesen der PDF-Datei');
|
||||
});
|
||||
return stream.pipe(res);
|
||||
}
|
||||
|
||||
// Nicht vorhanden: versionstreu generieren, speichern, dann senden
|
||||
const pdfBuffer = await generatePDFToBuffer(timesheetId, req);
|
||||
await savePdfBufferAtomic(absolutePath, pdfBuffer);
|
||||
|
||||
// Relativen Pfad in DB speichern (optional, Fehler nicht fatal)
|
||||
if (!timesheet.pdf_path) {
|
||||
db.run('UPDATE weekly_timesheets SET pdf_path = ? WHERE id = ?', [relativePath, timesheetId], (pathErr) => {
|
||||
if (pathErr) {
|
||||
console.warn('Warnung beim Speichern des PDF-Pfads:', pathErr.message);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return res.end(pdfBuffer);
|
||||
} catch (e) {
|
||||
console.error('Fehler beim Generieren/Speichern der PDF:', e);
|
||||
if (!res.headersSent) res.status(500);
|
||||
return res.end('Fehler beim Erstellen des PDFs');
|
||||
}
|
||||
}
|
||||
|
||||
// Zugriff erlauben wenn Verwaltung/Admin ODER wenn Timesheet dem User gehört
|
||||
if (isVerwaltung || timesheet.user_id === userId) {
|
||||
generatePDF(timesheetId, req, res);
|
||||
} else {
|
||||
res.status(403).send('Zugriff verweigert');
|
||||
}
|
||||
});
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user