diff --git a/public/js/dashboard.js b/public/js/dashboard.js index 408d890..8e42d63 100644 --- a/public/js/dashboard.js +++ b/public/js/dashboard.js @@ -64,6 +64,9 @@ document.addEventListener('DOMContentLoaded', async function() { // Ping-IP laden loadPingIP(); + // Statistiken laden + loadUserStats(); + loadWeek(); document.getElementById('prevWeek').addEventListener('click', function() { @@ -520,6 +523,7 @@ function updateOvertimeDisplay() { // Gesamtstunden berechnen - direkt aus DOM-Elementen lesen für Echtzeit-Aktualisierung let totalHours = 0; + let vacationHours = 0; const startDateObj = new Date(startDate); for (let i = 0; i < 7; i++) { const date = new Date(startDateObj); @@ -532,8 +536,30 @@ function updateOvertimeDisplay() { const sickCheckbox = document.querySelector(`input[data-date="${dateStr}"][data-field="sick_status"]`); const sickStatus = sickCheckbox ? sickCheckbox.checked : (currentEntries[dateStr]?.sick_status || false); + // Wenn Urlaub oder Krank, zähle nur diese Stunden (nicht zusätzlich Arbeitsstunden) if (vacationType === 'full') { - totalHours += 8; // Ganzer Tag Urlaub = 8 Stunden + vacationHours += 8; // Ganzer Tag Urlaub = 8 Stunden + } else if (vacationType === 'half') { + vacationHours += 4; // Halber Tag Urlaub = 4 Stunden + // Bei halbem Tag Urlaub können noch Arbeitsstunden vorhanden sein + const startInput = document.querySelector(`input[data-date="${dateStr}"][data-field="start_time"]`); + const endInput = document.querySelector(`input[data-date="${dateStr}"][data-field="end_time"]`); + const breakInput = document.querySelector(`input[data-date="${dateStr}"][data-field="break_minutes"]`); + + const startTime = startInput ? startInput.value : ''; + const endTime = endInput ? endInput.value : ''; + const breakMinutes = parseInt(breakInput ? breakInput.value : 0) || 0; + + if (startTime && endTime) { + const start = new Date(`2000-01-01T${startTime}`); + const end = new Date(`2000-01-01T${endTime}`); + const diffMs = end - start; + const hours = (diffMs / (1000 * 60 * 60)) - (breakMinutes / 60); + totalHours += hours; + } else if (currentEntries[dateStr]?.total_hours) { + // Fallback auf gespeicherte Werte + totalHours += parseFloat(currentEntries[dateStr].total_hours) || 0; + } } else if (sickStatus) { totalHours += 8; // Krank = 8 Stunden } else { @@ -559,24 +585,6 @@ function updateOvertimeDisplay() { } } - // Urlaubsstunden berechnen (Urlaub zählt als normale Arbeitszeit) - let vacationHours = 0; - const startDateObj2 = new Date(startDate); - for (let i = 0; i < 7; i++) { - const date = new Date(startDateObj2); - date.setDate(date.getDate() + i); - const dateStr = formatDate(date); - - const vacationSelect = document.querySelector(`select[data-date="${dateStr}"][data-field="vacation_type"]`); - const vacationType = vacationSelect ? vacationSelect.value : (currentEntries[dateStr]?.vacation_type || ''); - - if (vacationType === 'full') { - vacationHours += 8; // Ganzer Tag = 8 Stunden - } else if (vacationType === 'half') { - vacationHours += 4; // Halber Tag = 4 Stunden - } - } - // Genommene Überstunden berechnen - direkt aus DOM lesen let overtimeTaken = 0; const startDateObj3 = new Date(startDate); @@ -1172,7 +1180,8 @@ async function submitWeekWithReason(versionReason) { const versionText = result.version ? ` (Version ${result.version})` : ''; alert(`Stundenzettel wurde erfolgreich eingereicht${versionText}!`); loadWeek(); // Neu laden um Status zu aktualisieren - // Statistiken werden durch updateOvertimeDisplay() aktualisiert + // Statistiken aktualisieren + loadUserStats(); } else { console.error('Fehler-Details:', result); alert(result.error || 'Fehler beim Einreichen des Stundenzettels'); diff --git a/routes/user.js b/routes/user.js index 8f56a4e..e549ba3 100644 --- a/routes/user.js +++ b/routes/user.js @@ -260,18 +260,27 @@ function registerUserRoutes(app) { let weekVacationHours = 0; entries.forEach(entry => { - if (entry.total_hours) { - weekTotalHours += entry.total_hours; - } if (entry.overtime_taken_hours) { weekOvertimeTaken += entry.overtime_taken_hours; } + + // Urlaub hat Priorität - wenn Urlaub, zähle nur Urlaubsstunden, nicht zusätzlich Arbeitsstunden if (entry.vacation_type === 'full') { weekVacationDays += 1; - weekVacationHours += 8; + weekVacationHours += 8; // Ganzer Tag = 8 Stunden + // Bei vollem Tag Urlaub werden keine Arbeitsstunden gezählt } else if (entry.vacation_type === 'half') { weekVacationDays += 0.5; - weekVacationHours += 4; + weekVacationHours += 4; // Halber Tag = 4 Stunden + // Bei halbem Tag Urlaub können noch Arbeitsstunden vorhanden sein + if (entry.total_hours) { + weekTotalHours += entry.total_hours; + } + } else { + // Kein Urlaub - zähle nur Arbeitsstunden + if (entry.total_hours) { + weekTotalHours += entry.total_hours; + } } }); diff --git a/routes/verwaltung.js b/routes/verwaltung.js index a813604..c3a28e3 100644 --- a/routes/verwaltung.js +++ b/routes/verwaltung.js @@ -146,18 +146,27 @@ function registerVerwaltungRoutes(app) { let vacationHours = 0; entries.forEach(entry => { - if (entry.total_hours) { - totalHours += entry.total_hours; - } if (entry.overtime_taken_hours) { overtimeTaken += entry.overtime_taken_hours; } + + // Urlaub hat Priorität - wenn Urlaub, zähle nur Urlaubsstunden, nicht zusätzlich Arbeitsstunden if (entry.vacation_type === 'full') { vacationDays += 1; vacationHours += 8; // Ganzer Tag = 8 Stunden + // Bei vollem Tag Urlaub werden keine Arbeitsstunden gezählt } else if (entry.vacation_type === 'half') { vacationDays += 0.5; vacationHours += 4; // Halber Tag = 4 Stunden + // Bei halbem Tag Urlaub können noch Arbeitsstunden vorhanden sein + if (entry.total_hours) { + totalHours += entry.total_hours; + } + } else { + // Kein Urlaub - zähle nur Arbeitsstunden + if (entry.total_hours) { + totalHours += entry.total_hours; + } } }); diff --git a/services/pdf-service.js b/services/pdf-service.js index ef49e65..b8b7b15 100644 --- a/services/pdf-service.js +++ b/services/pdf-service.js @@ -221,15 +221,21 @@ function generatePDF(timesheetId, req, res) { doc.fontSize(10); } - if (entry.total_hours) { - totalHours += entry.total_hours; - } - - // Urlaubsstunden für Überstunden-Berechnung sammeln + // Urlaub hat Priorität - wenn Urlaub, zähle nur Urlaubsstunden, nicht zusätzlich Arbeitsstunden if (entry.vacation_type === 'full') { vacationHours += 8; // Ganzer Tag = 8 Stunden + // Bei vollem Tag Urlaub werden keine Arbeitsstunden gezählt } else if (entry.vacation_type === 'half') { vacationHours += 4; // Halber Tag = 4 Stunden + // Bei halbem Tag Urlaub können noch Arbeitsstunden vorhanden sein + if (entry.total_hours) { + totalHours += entry.total_hours; + } + } else { + // Kein Urlaub - zähle nur Arbeitsstunden + if (entry.total_hours) { + totalHours += entry.total_hours; + } } doc.moveDown(0.5); @@ -249,9 +255,9 @@ function generatePDF(timesheetId, req, res) { // Überstunden berechnen und anzeigen const wochenstunden = timesheet.wochenstunden || 0; - // Überstunden = Gesamtstunden - Wochenstunden - // Urlaub zählt als normale Arbeitszeit, daher sind Urlaubsstunden bereits in totalHours enthalten - const overtimeHours = totalHours - wochenstunden; + // Überstunden = (Tatsächliche Stunden + Urlaubsstunden) - Wochenstunden + const totalHoursWithVacation = totalHours + vacationHours; + const overtimeHours = totalHoursWithVacation - wochenstunden; doc.moveDown(0.3); doc.font('Helvetica-Bold'); @@ -432,14 +438,21 @@ function generatePDFToBuffer(timesheetId, req) { doc.fontSize(10); } - if (entry.total_hours) { - totalHours += entry.total_hours; - } - + // Urlaub hat Priorität - wenn Urlaub, zähle nur Urlaubsstunden, nicht zusätzlich Arbeitsstunden if (entry.vacation_type === 'full') { - vacationHours += 8; + vacationHours += 8; // Ganzer Tag = 8 Stunden + // Bei vollem Tag Urlaub werden keine Arbeitsstunden gezählt } else if (entry.vacation_type === 'half') { - vacationHours += 4; + vacationHours += 4; // Halber Tag = 4 Stunden + // Bei halbem Tag Urlaub können noch Arbeitsstunden vorhanden sein + if (entry.total_hours) { + totalHours += entry.total_hours; + } + } else { + // Kein Urlaub - zähle nur Arbeitsstunden + if (entry.total_hours) { + totalHours += entry.total_hours; + } } doc.moveDown(0.5); @@ -457,7 +470,9 @@ function generatePDFToBuffer(timesheetId, req) { doc.text(`Gesamtstunden: ${totalHours.toFixed(2)} h`, 50, doc.y); const wochenstunden = timesheet.wochenstunden || 0; - const overtimeHours = totalHours - wochenstunden; + // Überstunden = (Tatsächliche Stunden + Urlaubsstunden) - Wochenstunden + const totalHoursWithVacation = totalHours + vacationHours; + const overtimeHours = totalHoursWithVacation - wochenstunden; doc.moveDown(0.3); doc.font('Helvetica-Bold'); diff --git a/views/dashboard.ejs b/views/dashboard.ejs index cda162f..a934c30 100644 --- a/views/dashboard.ejs +++ b/views/dashboard.ejs @@ -55,6 +55,53 @@
Stunden werden automatisch gespeichert. Am Ende der Woche können Sie die Stunden abschicken.
+ + +Ihre IP-Adresse für automatische Zeiterfassung
+