BugFix Projektauswertung
This commit is contained in:
@@ -38,10 +38,15 @@ function registerVerwaltungRoutes(app) {
|
|||||||
WHERE wt.status = 'eingereicht'
|
WHERE wt.status = 'eingereicht'
|
||||||
ORDER BY wt.week_start DESC, wt.user_id, wt.version DESC
|
ORDER BY wt.week_start DESC, wt.user_id, wt.version DESC
|
||||||
`, (err, timesheets) => {
|
`, (err, timesheets) => {
|
||||||
|
if (err) {
|
||||||
|
console.error('Fehler beim Laden der Stundenzettel (Verwaltung):', err);
|
||||||
|
return res.status(500).send('Fehler beim Laden der Verwaltungsdaten. Bitte die Server-Logs prüfen oder die Datenbank-Migrationen ausführen.');
|
||||||
|
}
|
||||||
|
|
||||||
// Gruppiere nach Mitarbeiter, dann nach Kalenderwoche
|
// Gruppiere nach Mitarbeiter, dann nach Kalenderwoche
|
||||||
// Struktur: { [user_id]: { user: {...}, weeks: { [week_key]: {...} } } }
|
// Struktur: { [user_id]: { user: {...}, weeks: { [week_key]: {...} } } }
|
||||||
const groupedByEmployee = {};
|
const groupedByEmployee = {};
|
||||||
|
|
||||||
(timesheets || []).forEach(ts => {
|
(timesheets || []).forEach(ts => {
|
||||||
const userId = ts.user_id;
|
const userId = ts.user_id;
|
||||||
const weekKey = `${ts.week_start}_${ts.week_end}`;
|
const weekKey = `${ts.week_start}_${ts.week_end}`;
|
||||||
@@ -152,37 +157,57 @@ function registerVerwaltungRoutes(app) {
|
|||||||
|
|
||||||
// Projektauswertung nach Mitarbeitern für eine Projektnummer
|
// Projektauswertung nach Mitarbeitern für eine Projektnummer
|
||||||
app.get('/verwaltung/projektauswertung', requireVerwaltung, (req, res) => {
|
app.get('/verwaltung/projektauswertung', requireVerwaltung, (req, res) => {
|
||||||
|
let session;
|
||||||
|
try {
|
||||||
|
session = req.session || {};
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Fehler beim Zugriff auf die Session (Projektauswertung):', e);
|
||||||
|
return res.status(500).send('Fehler: Session nicht verfügbar. Bitte erneut anmelden.');
|
||||||
|
}
|
||||||
|
const userForView = {
|
||||||
|
firstname: session.firstname ?? '',
|
||||||
|
lastname: session.lastname ?? '',
|
||||||
|
roles: Array.isArray(session.roles) ? session.roles : [],
|
||||||
|
currentRole: session.currentRole || 'verwaltung'
|
||||||
|
};
|
||||||
|
|
||||||
const projectNumberRaw = req.query.project ? String(req.query.project).trim() : '';
|
const projectNumberRaw = req.query.project ? String(req.query.project).trim() : '';
|
||||||
const projectNumber = projectNumberRaw || null;
|
const projectNumber = projectNumberRaw || null;
|
||||||
|
|
||||||
|
const doRender = (locals) => {
|
||||||
|
try {
|
||||||
|
return res.render('projekt-auswertung', locals);
|
||||||
|
} catch (e) {
|
||||||
|
console.error('Fehler beim Rendern der Projektauswertung:', e);
|
||||||
|
if (!res.headersSent) {
|
||||||
|
res.status(500).send('Fehler beim Anzeigen der Seite. Bitte Server-Logs prüfen.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
if (!projectNumber) {
|
if (!projectNumber) {
|
||||||
// Nur Formular anzeigen, noch keine Auswertung
|
// Nur Formular anzeigen, noch keine Auswertung
|
||||||
return res.render('projekt-auswertung', {
|
return doRender({
|
||||||
user: {
|
user: userForView,
|
||||||
firstname: req.session.firstname,
|
|
||||||
lastname: req.session.lastname,
|
|
||||||
roles: req.session.roles || [],
|
|
||||||
currentRole: req.session.currentRole || 'verwaltung'
|
|
||||||
},
|
|
||||||
projectNumber: '',
|
projectNumber: '',
|
||||||
results: [],
|
results: [],
|
||||||
totalProjectHours: 0,
|
totalProjectHours: 0,
|
||||||
hasResults: false
|
hasResults: false,
|
||||||
|
totalProjectHoursFormatted: '0:00',
|
||||||
|
breakdownByUser: {},
|
||||||
|
projectNumberError: null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValidProjectNumber(projectNumber)) {
|
if (!isValidProjectNumber(projectNumber)) {
|
||||||
return res.render('projekt-auswertung', {
|
return doRender({
|
||||||
user: {
|
user: userForView,
|
||||||
firstname: req.session.firstname,
|
|
||||||
lastname: req.session.lastname,
|
|
||||||
roles: req.session.roles || [],
|
|
||||||
currentRole: req.session.currentRole || 'verwaltung'
|
|
||||||
},
|
|
||||||
projectNumber: projectNumberRaw,
|
projectNumber: projectNumberRaw,
|
||||||
results: [],
|
results: [],
|
||||||
totalProjectHours: 0,
|
totalProjectHours: 0,
|
||||||
hasResults: false,
|
hasResults: false,
|
||||||
|
totalProjectHoursFormatted: '0:00',
|
||||||
|
breakdownByUser: {},
|
||||||
projectNumberError: 'Die Projektnummer muss 7 Ziffern haben, mit 5 beginnen, gefolgt vom Jahr (YY) und 4 Ziffern (z.B. 5260001).'
|
projectNumberError: 'Die Projektnummer muss 7 Ziffern haben, mit 5 beginnen, gefolgt vom Jahr (YY) und 4 Ziffern (z.B. 5260001).'
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -224,7 +249,7 @@ function registerVerwaltungRoutes(app) {
|
|||||||
db.all(sql, params, (err, rows) => {
|
db.all(sql, params, (err, rows) => {
|
||||||
if (err) {
|
if (err) {
|
||||||
console.error('Fehler bei der Projektauswertung:', err);
|
console.error('Fehler bei der Projektauswertung:', err);
|
||||||
return res.status(500).send('Fehler bei der Projektauswertung');
|
return res.status(500).send('Fehler bei der Projektauswertung: ' + (err.message || String(err)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const rawResults = (rows || []).map((row) => {
|
const rawResults = (rows || []).map((row) => {
|
||||||
@@ -247,19 +272,15 @@ function registerVerwaltungRoutes(app) {
|
|||||||
const totalProjectHoursFormatted = minutesToHhMm(totalProjectMinutes);
|
const totalProjectHoursFormatted = minutesToHhMm(totalProjectMinutes);
|
||||||
|
|
||||||
if (results.length === 0) {
|
if (results.length === 0) {
|
||||||
return res.render('projekt-auswertung', {
|
return doRender({
|
||||||
user: {
|
user: userForView,
|
||||||
firstname: req.session.firstname,
|
|
||||||
lastname: req.session.lastname,
|
|
||||||
roles: req.session.roles || [],
|
|
||||||
currentRole: req.session.currentRole || 'verwaltung'
|
|
||||||
},
|
|
||||||
projectNumber: projectNumberRaw,
|
projectNumber: projectNumberRaw,
|
||||||
results,
|
results,
|
||||||
totalProjectHours,
|
totalProjectHours,
|
||||||
totalProjectHoursFormatted,
|
totalProjectHoursFormatted,
|
||||||
hasResults: false,
|
hasResults: false,
|
||||||
breakdownByUser: {}
|
breakdownByUser: {},
|
||||||
|
projectNumberError: null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -343,19 +364,15 @@ function registerVerwaltungRoutes(app) {
|
|||||||
|
|
||||||
pending -= 1;
|
pending -= 1;
|
||||||
if (pending === 0) {
|
if (pending === 0) {
|
||||||
res.render('projekt-auswertung', {
|
doRender({
|
||||||
user: {
|
user: userForView,
|
||||||
firstname: req.session.firstname,
|
|
||||||
lastname: req.session.lastname,
|
|
||||||
roles: req.session.roles || [],
|
|
||||||
currentRole: req.session.currentRole || 'verwaltung'
|
|
||||||
},
|
|
||||||
projectNumber: projectNumberRaw,
|
projectNumber: projectNumberRaw,
|
||||||
results,
|
results,
|
||||||
totalProjectHours,
|
totalProjectHours,
|
||||||
totalProjectHoursFormatted,
|
totalProjectHoursFormatted,
|
||||||
hasResults: results.length > 0,
|
hasResults: results.length > 0,
|
||||||
breakdownByUser
|
breakdownByUser,
|
||||||
|
projectNumberError: null
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -289,7 +289,7 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="pdf-viewer-wrapper">
|
<div class="pdf-viewer-wrapper">
|
||||||
<iframe
|
<iframe
|
||||||
src="/api/timesheet/pdf/<%= ts.id %>?inline=true"
|
data-src="/api/timesheet/pdf/<%= ts.id %>?inline=true"
|
||||||
class="pdf-iframe"
|
class="pdf-iframe"
|
||||||
frameborder="0"
|
frameborder="0"
|
||||||
type="application/pdf"
|
type="application/pdf"
|
||||||
@@ -939,7 +939,7 @@
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// PDF-Vorschau ein-/ausblenden
|
// PDF-Vorschau ein-/ausblenden (PDF erst bei Klick laden)
|
||||||
document.querySelectorAll('.toggle-pdf-btn').forEach(btn => {
|
document.querySelectorAll('.toggle-pdf-btn').forEach(btn => {
|
||||||
btn.addEventListener('click', function() {
|
btn.addEventListener('click', function() {
|
||||||
const timesheetId = this.dataset.timesheetId;
|
const timesheetId = this.dataset.timesheetId;
|
||||||
@@ -965,11 +965,12 @@
|
|||||||
arrowIcon.textContent = '▼';
|
arrowIcon.textContent = '▼';
|
||||||
this.classList.add('active');
|
this.classList.add('active');
|
||||||
|
|
||||||
// Setze iframe src wenn noch nicht gesetzt (für besseres Laden)
|
// iframe-src erst jetzt setzen (lazy load), falls noch nicht gesetzt
|
||||||
if (iframe) {
|
if (iframe) {
|
||||||
const currentSrc = iframe.src || iframe.getAttribute('src');
|
const currentSrc = iframe.getAttribute('src');
|
||||||
if (!currentSrc || !currentSrc.includes('inline=true')) {
|
if (!currentSrc) {
|
||||||
iframe.src = `/api/timesheet/pdf/${timesheetId}?inline=true`;
|
const dataSrc = iframe.getAttribute('data-src') || `/api/timesheet/pdf/${timesheetId}?inline=true`;
|
||||||
|
iframe.setAttribute('src', dataSrc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user