Umstellung auf Arbeitstage

This commit is contained in:
2026-02-03 22:32:49 +01:00
parent 4be9a365b3
commit a3efbb43ae
11 changed files with 304 additions and 157 deletions

View File

@@ -25,6 +25,7 @@ document.addEventListener('DOMContentLoaded', function() {
roles: roles,
personalnummer: document.getElementById('personalnummer').value,
wochenstunden: document.getElementById('wochenstunden').value,
arbeitstage: document.getElementById('arbeitstage').value,
urlaubstage: document.getElementById('urlaubstage').value
};
@@ -315,6 +316,7 @@ async function saveUser(userId) {
const personalnummer = row.querySelector('input[data-field="personalnummer"]').value;
const wochenstunden = row.querySelector('input[data-field="wochenstunden"]').value;
const arbeitstage = row.querySelector('input[data-field="arbeitstage"]').value;
const urlaubstage = row.querySelector('input[data-field="urlaubstage"]').value;
// Rollen aus Checkboxen sammeln
@@ -336,6 +338,7 @@ async function saveUser(userId) {
body: JSON.stringify({
personalnummer: personalnummer || null,
wochenstunden: wochenstunden || null,
arbeitstage: arbeitstage || 5,
urlaubstage: urlaubstage || null,
roles: roles
})

View File

@@ -4,6 +4,7 @@ let currentWeekStart = getMonday(new Date());
let currentEntries = {};
let currentHolidayDates = new Set(); // Feiertage der aktuellen Woche (YYYY-MM-DD)
let userWochenstunden = 0; // Wochenstunden des Users
let userArbeitstage = 5; // Arbeitstage pro Woche des Users (Standard: 5)
let weekendPercentages = { saturday: 100, sunday: 100 }; // Wochenend-Prozentsätze (100% = normal)
let latestSubmittedTimesheetId = null; // ID der neuesten eingereichten Version
@@ -303,17 +304,24 @@ function getWeekday(dateStr) {
return days[d.getDay()];
}
// Hilfsfunktion: Berechnet die Stunden pro Tag (Wochenarbeitszeit / Arbeitstage)
function getFullDayHours() {
return userWochenstunden && userArbeitstage ? (userWochenstunden / userArbeitstage) : 8;
}
// Woche laden
async function loadWeek() {
try {
// User-Daten laden (Wochenstunden)
// User-Daten laden (Wochenstunden, Arbeitstage)
try {
const userResponse = await fetch('/api/user/data');
const userData = await userResponse.json();
userWochenstunden = userData.wochenstunden || 0;
userArbeitstage = userData.arbeitstage || 5;
} catch (error) {
console.warn('Konnte User-Daten nicht laden:', error);
userWochenstunden = 0;
userArbeitstage = 5;
}
const parts = currentWeekStart.split('-');
@@ -420,7 +428,7 @@ function renderWeek() {
// Bei Feiertag, ganztägigem Urlaub oder Krank gilt der Tag als ausgefüllt
// Bei 8 Überstunden (ganzer Tag) gilt der Tag auch als ausgefüllt
const overtimeValue = overtimeTaken ? parseFloat(overtimeTaken) : 0;
const fullDayHours = userWochenstunden ? (userWochenstunden / 5) : 8;
const fullDayHours = getFullDayHours();
const isFullDayOvertime = overtimeValue > 0 && Math.abs(overtimeValue - fullDayHours) < 0.01;
if (i < 5 && !isHoliday && vacationType !== 'full' && !sickStatus && !isFullDayOvertime && (!startTime || !endTime || startTime.trim() === '' || endTime.trim() === '')) {
@@ -434,7 +442,7 @@ function renderWeek() {
// Wochenend-Prozentsätze: Nur auf tatsächlich gearbeitete Stunden anwenden (nicht auf Urlaub, Krankheit, Feiertage)
let hoursToAdd = 0;
if (isHoliday) {
hoursToAdd = 8 + (hours || 0); // 8h Feiertag + gearbeitete Stunden (= Überstunden)
hoursToAdd = fullDayHours + (hours || 0); // (Wochenarbeitszeit / Arbeitstage) Feiertag + gearbeitete Stunden (= Überstunden)
} else {
hoursToAdd = hours || 0;
// Wochenend-Prozentsatz anwenden (nur wenn weekend_travel aktiviert UND es ist ein Wochenendtag)
@@ -482,7 +490,7 @@ function renderWeek() {
data-date="${dateStr}" data-field="break_minutes"
${timeFieldsDisabled} ${disabled} oninput="saveEntry(this)" onchange="saveEntry(this)">
</td>
<td><strong id="hours_${dateStr}">${isFullDayVacation ? '8.00 h (Urlaub)' : isSick ? '8.00 h (Krank)' : isHoliday && !hours ? '8.00 h (Feiertag)' : isHoliday && hours ? '8.00 + ' + hours.toFixed(2) + ' h (Überst.)' : hours.toFixed(2) + ' h'}</strong></td>
<td><strong id="hours_${dateStr}">${isFullDayVacation ? fullDayHours.toFixed(2) + ' h (Urlaub)' : isSick ? fullDayHours.toFixed(2) + ' h (Krank)' : isHoliday && !hours ? fullDayHours.toFixed(2) + ' h (Feiertag)' : isHoliday && hours ? fullDayHours.toFixed(2) + ' + ' + hours.toFixed(2) + ' h (Überst.)' : hours.toFixed(2) + ' h'}</strong></td>
</tr>
<tr class="activities-row">
<td colspan="6" class="activities-cell">
@@ -640,15 +648,16 @@ function renderWeek() {
}
// Sollstunden berechnen
const sollStunden = (userWochenstunden / 5) * workdays;
const sollStunden = (userWochenstunden / userArbeitstage) * workdays;
// Urlaubsstunden berechnen (Urlaub zählt als normale Arbeitszeit)
let vacationHours = 0;
const fullDayHours = getFullDayHours();
Object.values(currentEntries).forEach(e => {
if (e.vacation_type === 'full') {
vacationHours += 8; // Ganzer Tag = 8 Stunden
vacationHours += fullDayHours; // Ganzer Tag = (Wochenarbeitszeit / Arbeitstage) Stunden
} else if (e.vacation_type === 'half') {
vacationHours += 4; // Halber Tag = 4 Stunden
vacationHours += fullDayHours / 2; // Halber Tag = (Wochenarbeitszeit / Arbeitstage) / 2 Stunden
}
});
@@ -684,7 +693,7 @@ function updateOvertimeDisplay() {
}
// Sollstunden berechnen
const sollStunden = (userWochenstunden / 5) * workdays;
const sollStunden = (userWochenstunden / userArbeitstage) * workdays;
// Gesamtstunden berechnen - direkt aus DOM-Elementen lesen für Echtzeit-Aktualisierung
let totalHours = 0;
@@ -715,9 +724,9 @@ function updateOvertimeDisplay() {
// Wenn Urlaub oder Krank, zähle nur diese Stunden (nicht zusätzlich Arbeitsstunden)
if (vacationType === 'full') {
vacationHours += 8; // Ganzer Tag Urlaub = 8 Stunden
vacationHours += fullDayHours; // Ganzer Tag Urlaub = (Wochenarbeitszeit / Arbeitstage) Stunden
} else if (vacationType === 'half') {
vacationHours += 4; // Halber Tag Urlaub = 4 Stunden
vacationHours += fullDayHours / 2; // Halber Tag Urlaub = (Wochenarbeitszeit / Arbeitstage) / 2 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"]`);
@@ -776,9 +785,9 @@ function updateOvertimeDisplay() {
totalHours += hours;
}
} else if (sickStatus) {
totalHours += 8; // Krank = 8 Stunden
totalHours += fullDayHours; // Krank = (Wochenarbeitszeit / Arbeitstage) Stunden
} else if (currentHolidayDates.has(dateStr)) {
// Feiertag: 8h Basis + gearbeitete Stunden (jede Stunde = Überstunde)
// Feiertag: (Wochenarbeitszeit / Arbeitstage) Basis + gearbeitete Stunden (jede Stunde = Überstunde)
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 startTime = startInput ? startInput.value : '';
@@ -793,7 +802,7 @@ function updateOvertimeDisplay() {
} else if (currentEntries[dateStr]?.total_hours) {
worked = parseFloat(currentEntries[dateStr].total_hours) || 0;
}
totalHours += 8 + worked; // 8h Feiertag + gearbeitete Stunden (= Überstunden)
totalHours += fullDayHours + worked; // (Wochenarbeitszeit / Arbeitstage) Feiertag + gearbeitete Stunden (= Überstunden)
} else {
// Wenn 8 Überstunden (ganzer Tag) eingetragen sind, zählt der Tag als 0 Stunden
if (isFullDayOvertime) {
@@ -902,7 +911,7 @@ function handleOvertimeChange(dateStr, overtimeHours) {
return;
}
const fullDayHours = userWochenstunden / 5;
const fullDayHours = getFullDayHours();
const overtimeValue = parseFloat(overtimeHours) || 0;
// Prüfe ob ganzer Tag Überstunden
@@ -1204,11 +1213,11 @@ function checkWeekComplete() {
const overtimeValue = overtimeInput ? parseFloat(overtimeInput.value) || 0 : (entry.overtime_taken_hours ? parseFloat(entry.overtime_taken_hours) : 0);
// Berechne fullDayHours (normalerweise 8 Stunden)
const fullDayHours = userWochenstunden ? (userWochenstunden / 5) : 8;
const fullDayHours = getFullDayHours();
// Wenn 8 Überstunden (ganzer Tag) eingetragen sind, ist der Tag ausgefüllt
// Wenn Überstunden (ganzer Tag) eingetragen sind, ist der Tag ausgefüllt
if (overtimeValue > 0 && Math.abs(overtimeValue - fullDayHours) < 0.01) {
continue; // Tag ist ausgefüllt (8 Überstunden = ganzer Tag)
continue; // Tag ist ausgefüllt (Überstunden = ganzer Tag)
}
// Prüfe IMMER direkt die Input-Felder im DOM (das ist die zuverlässigste Quelle)
@@ -1231,8 +1240,17 @@ function checkWeekComplete() {
fullDayHours: fullDayHours
});
// Wenn Überstunden > fullDayHours, dann müssen Start/Ende vorhanden sein
if (overtimeValue > fullDayHours) {
if (!startTime || !endTime || startTime === '' || endTime === '') {
allWeekdaysFilled = false;
missingFields.push(formatDateDE(dateStr) + ' (bei Überstunden > ' + fullDayHours.toFixed(2) + 'h müssen Start/Ende vorhanden sein)');
continue; // Weiter zum nächsten Tag
}
}
// Bei halbem Tag Urlaub oder keinem Urlaub müssen Start- und Endzeit vorhanden sein
// (außer wenn 8 Überstunden eingetragen sind, dann sind Start/Ende nicht nötig)
// (außer wenn Überstunden = fullDayHours eingetragen sind, dann sind Start/Ende nicht nötig)
if (!startTime || !endTime || startTime === '' || endTime === '') {
allWeekdaysFilled = false;
missingFields.push(formatDateDE(dateStr));
@@ -1338,7 +1356,7 @@ async function submitWeek() {
// Prüfe ob 8 Überstunden eingetragen sind (dann ist der Tag auch ausgefüllt, Start/Ende nicht nötig)
const overtimeInput = document.querySelector(`input[data-date="${dateStr}"][data-field="overtime_taken_hours"]`);
const overtimeValue = overtimeInput ? parseFloat(overtimeInput.value) || 0 : (entry.overtime_taken_hours ? parseFloat(entry.overtime_taken_hours) : 0);
const fullDayHours = userWochenstunden ? (userWochenstunden / 5) : 8;
const fullDayHours = getFullDayHours();
// Wenn 8 Überstunden (ganzer Tag) eingetragen sind, ist der Tag ausgefüllt
if (overtimeValue > 0 && Math.abs(overtimeValue - fullDayHours) < 0.01) {