// Verwaltung Routes const { db } = require('../database'); const { requireVerwaltung } = require('../middleware/auth'); // Routes registrieren function registerVerwaltungRoutes(app) { // Verwaltungs-Bereich app.get('/verwaltung', requireVerwaltung, (req, res) => { db.all(` SELECT wt.*, u.firstname, u.lastname, u.username, u.personalnummer, u.wochenstunden, u.urlaubstage, dl.firstname as downloaded_by_firstname, dl.lastname as downloaded_by_lastname, (SELECT COUNT(*) FROM weekly_timesheets wt2 WHERE wt2.user_id = wt.user_id AND wt2.week_start = wt.week_start AND wt2.week_end = wt.week_end) as total_versions FROM weekly_timesheets wt JOIN users u ON wt.user_id = u.id LEFT JOIN users dl ON wt.pdf_downloaded_by = dl.id WHERE wt.status = 'eingereicht' ORDER BY wt.week_start DESC, wt.user_id, wt.version DESC `, (err, timesheets) => { // Gruppiere nach Mitarbeiter, dann nach Kalenderwoche // Struktur: { [user_id]: { user: {...}, weeks: { [week_key]: {...} } } } const groupedByEmployee = {}; (timesheets || []).forEach(ts => { const userId = ts.user_id; const weekKey = `${ts.week_start}_${ts.week_end}`; // Level 1: Mitarbeiter if (!groupedByEmployee[userId]) { groupedByEmployee[userId] = { user: { id: ts.user_id, firstname: ts.firstname, lastname: ts.lastname, username: ts.username, personalnummer: ts.personalnummer, wochenstunden: ts.wochenstunden, urlaubstage: ts.urlaubstage }, weeks: {} }; } // Level 2: Kalenderwoche if (!groupedByEmployee[userId].weeks[weekKey]) { groupedByEmployee[userId].weeks[weekKey] = { week_start: ts.week_start, week_end: ts.week_end, total_versions: ts.total_versions, versions: [] }; } // Level 3: Versionen groupedByEmployee[userId].weeks[weekKey].versions.push(ts); }); // Sortierung: Mitarbeiter nach Name, Wochen nach Datum (neueste zuerst) const sortedEmployees = Object.values(groupedByEmployee).map(employee => { // Wochen innerhalb jedes Mitarbeiters sortieren const sortedWeeks = Object.values(employee.weeks).sort((a, b) => { return new Date(b.week_start) - new Date(a.week_start); }); return { ...employee, weeks: sortedWeeks }; }).sort((a, b) => { // Mitarbeiter nach Nachname, dann Vorname sortieren const nameA = `${a.user.lastname} ${a.user.firstname}`.toLowerCase(); const nameB = `${b.user.lastname} ${b.user.firstname}`.toLowerCase(); return nameA.localeCompare(nameB); }); res.render('verwaltung', { groupedByEmployee: sortedEmployees, user: { firstname: req.session.firstname, lastname: req.session.lastname, roles: req.session.roles || [], currentRole: req.session.currentRole || 'verwaltung' } }); }); }); // API: Überstunden- und Urlaubsstatistiken für einen User abrufen app.get('/api/verwaltung/user/:id/stats', requireVerwaltung, (req, res) => { const userId = req.params.id; const { week_start, week_end } = req.query; // User-Daten abrufen db.get('SELECT wochenstunden, urlaubstage FROM users WHERE id = ?', [userId], (err, user) => { if (err || !user) { return res.status(500).json({ error: 'Fehler beim Abrufen der User-Daten' }); } const wochenstunden = user.wochenstunden || 0; const urlaubstage = user.urlaubstage || 0; // Einträge für die Woche abrufen db.all(`SELECT date, total_hours, overtime_taken_hours, vacation_type FROM timesheet_entries WHERE user_id = ? AND date >= ? AND date <= ? ORDER BY date`, [userId, week_start, week_end], (err, entries) => { if (err) { return res.status(500).json({ error: 'Fehler beim Abrufen der Einträge' }); } // Berechnungen let totalHours = 0; let overtimeTaken = 0; let vacationDays = 0; let vacationHours = 0; entries.forEach(entry => { if (entry.total_hours) { totalHours += entry.total_hours; } if (entry.overtime_taken_hours) { overtimeTaken += entry.overtime_taken_hours; } if (entry.vacation_type === 'full') { vacationDays += 1; vacationHours += 8; // Ganzer Tag = 8 Stunden } else if (entry.vacation_type === 'half') { vacationDays += 0.5; vacationHours += 4; // Halber Tag = 4 Stunden } }); // Anzahl Werktage berechnen (Montag-Freitag) const startDate = new Date(week_start); const endDate = new Date(week_end); let workdays = 0; for (let d = new Date(startDate); d <= endDate; d.setDate(d.getDate() + 1)) { const day = d.getDay(); if (day >= 1 && day <= 5) { // Montag bis Freitag workdays++; } } // Sollstunden berechnen const sollStunden = (wochenstunden / 5) * workdays; // Überstunden berechnen: Urlaub zählt als normale Arbeitszeit // Überstunden = (Tatsächliche Stunden + Urlaubsstunden) - Sollstunden const totalHoursWithVacation = totalHours + vacationHours; const overtimeHours = totalHoursWithVacation - sollStunden; const remainingOvertime = overtimeHours - overtimeTaken; // Verbleibende Urlaubstage const remainingVacation = urlaubstage - vacationDays; res.json({ wochenstunden, urlaubstage, totalHours, sollStunden, overtimeHours, overtimeTaken, remainingOvertime, vacationDays, remainingVacation, workdays }); }); }); }); // API: Admin-Kommentar speichern app.put('/api/verwaltung/timesheet/:id/comment', requireVerwaltung, (req, res) => { const timesheetId = req.params.id; const { comment } = req.body; db.run('UPDATE weekly_timesheets SET admin_comment = ? WHERE id = ?', [comment ? comment.trim() : null, timesheetId], (err) => { if (err) { console.error('Fehler beim Speichern des Kommentars:', err); return res.status(500).json({ error: 'Fehler beim Speichern des Kommentars' }); } res.json({ success: true }); }); }); } module.exports = registerVerwaltungRoutes;