BROKEN
This commit is contained in:
179
routes/user.js
179
routes/user.js
@@ -51,6 +51,22 @@ function registerUserRoutes(app) {
|
||||
});
|
||||
});
|
||||
|
||||
// API: Client-IP abrufen
|
||||
app.get('/api/user/client-ip', requireAuth, (req, res) => {
|
||||
// Versuche verschiedene Methoden, um die Client-IP zu erhalten
|
||||
const clientIp = req.ip ||
|
||||
req.connection.remoteAddress ||
|
||||
req.socket.remoteAddress ||
|
||||
(req.headers['x-forwarded-for'] ? req.headers['x-forwarded-for'].split(',')[0].trim() : null) ||
|
||||
req.headers['x-real-ip'] ||
|
||||
'unknown';
|
||||
|
||||
// Entferne IPv6-Präfix falls vorhanden (::ffff:192.168.1.1 -> 192.168.1.1)
|
||||
const cleanIp = clientIp.replace(/^::ffff:/, '');
|
||||
|
||||
res.json({ client_ip: cleanIp });
|
||||
});
|
||||
|
||||
// API: Ping-IP abrufen
|
||||
app.get('/api/user/ping-ip', requireAuth, (req, res) => {
|
||||
const userId = req.session.userId;
|
||||
@@ -120,6 +136,52 @@ function registerUserRoutes(app) {
|
||||
res.json({ success: true, currentRole: role });
|
||||
});
|
||||
|
||||
// API: Verplante Urlaubstage (alle Wochen, auch nicht-eingereichte)
|
||||
app.get('/api/user/planned-vacation', requireAuth, (req, res) => {
|
||||
const userId = req.session.userId;
|
||||
const { getCalendarWeek } = require('../helpers/utils');
|
||||
|
||||
db.all(`SELECT date, vacation_type FROM timesheet_entries
|
||||
WHERE user_id = ? AND vacation_type IS NOT NULL AND vacation_type != ''`,
|
||||
[userId],
|
||||
(err, entries) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Fehler beim Abrufen der verplanten Tage' });
|
||||
}
|
||||
|
||||
let plannedDays = 0;
|
||||
const weeksMap = {}; // { KW: { year: YYYY, week: KW, days: X } }
|
||||
|
||||
entries.forEach(entry => {
|
||||
const dayValue = entry.vacation_type === 'full' ? 1 : 0.5;
|
||||
plannedDays += dayValue;
|
||||
|
||||
// Berechne Kalenderwoche
|
||||
const date = new Date(entry.date);
|
||||
const year = date.getFullYear();
|
||||
const week = getCalendarWeek(entry.date);
|
||||
const weekKey = `${year}-KW${week}`;
|
||||
|
||||
if (!weeksMap[weekKey]) {
|
||||
weeksMap[weekKey] = { year, week, days: 0 };
|
||||
}
|
||||
weeksMap[weekKey].days += dayValue;
|
||||
});
|
||||
|
||||
// Konvertiere zu sortiertem Array
|
||||
const weeks = Object.values(weeksMap).sort((a, b) => {
|
||||
if (a.year !== b.year) return a.year - b.year;
|
||||
return a.week - b.week;
|
||||
});
|
||||
|
||||
res.json({
|
||||
plannedVacationDays: plannedDays,
|
||||
weeks: weeks
|
||||
});
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
// API: Gesamtstatistiken für Mitarbeiter (Überstunden und Urlaubstage)
|
||||
app.get('/api/user/stats', requireAuth, (req, res) => {
|
||||
const userId = req.session.userId;
|
||||
@@ -134,29 +196,66 @@ function registerUserRoutes(app) {
|
||||
const urlaubstage = user.urlaubstage || 0;
|
||||
const overtimeOffsetHours = user.overtime_offset_hours ? parseFloat(user.overtime_offset_hours) : 0;
|
||||
|
||||
// Alle eingereichten Wochen abrufen
|
||||
db.all(`SELECT DISTINCT week_start, week_end
|
||||
FROM weekly_timesheets
|
||||
WHERE user_id = ? AND status = 'eingereicht'
|
||||
ORDER BY week_start`,
|
||||
// Verplante Urlaubstage berechnen (alle Wochen, auch nicht-eingereichte)
|
||||
const { getCalendarWeek } = require('../helpers/utils');
|
||||
db.all(`SELECT date, vacation_type FROM timesheet_entries
|
||||
WHERE user_id = ? AND vacation_type IS NOT NULL AND vacation_type != ''`,
|
||||
[userId],
|
||||
(err, weeks) => {
|
||||
(err, allVacationEntries) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Fehler beim Abrufen der Wochen' });
|
||||
return res.status(500).json({ error: 'Fehler beim Abrufen der verplanten Tage' });
|
||||
}
|
||||
|
||||
// Wenn keine Wochen vorhanden
|
||||
if (!weeks || weeks.length === 0) {
|
||||
return res.json({
|
||||
currentOvertime: overtimeOffsetHours,
|
||||
remainingVacation: urlaubstage,
|
||||
totalOvertimeHours: 0,
|
||||
totalOvertimeTaken: 0,
|
||||
totalVacationDays: 0,
|
||||
urlaubstage: urlaubstage,
|
||||
overtimeOffsetHours: overtimeOffsetHours
|
||||
});
|
||||
}
|
||||
let plannedVacationDays = 0;
|
||||
const weeksMap = {}; // { KW: { year: YYYY, week: KW, days: X } }
|
||||
|
||||
(allVacationEntries || []).forEach(entry => {
|
||||
const dayValue = entry.vacation_type === 'full' ? 1 : 0.5;
|
||||
plannedVacationDays += dayValue;
|
||||
|
||||
// Berechne Kalenderwoche
|
||||
const date = new Date(entry.date);
|
||||
const year = date.getFullYear();
|
||||
const week = getCalendarWeek(entry.date);
|
||||
const weekKey = `${year}-KW${week}`;
|
||||
|
||||
if (!weeksMap[weekKey]) {
|
||||
weeksMap[weekKey] = { year, week, days: 0 };
|
||||
}
|
||||
weeksMap[weekKey].days += dayValue;
|
||||
});
|
||||
|
||||
// Konvertiere zu sortiertem Array
|
||||
const plannedWeeks = Object.values(weeksMap).sort((a, b) => {
|
||||
if (a.year !== b.year) return a.year - b.year;
|
||||
return a.week - b.week;
|
||||
});
|
||||
|
||||
// Alle eingereichten Wochen abrufen
|
||||
db.all(`SELECT DISTINCT week_start, week_end
|
||||
FROM weekly_timesheets
|
||||
WHERE user_id = ? AND status = 'eingereicht'
|
||||
ORDER BY week_start`,
|
||||
[userId],
|
||||
(err, weeks) => {
|
||||
if (err) {
|
||||
return res.status(500).json({ error: 'Fehler beim Abrufen der Wochen' });
|
||||
}
|
||||
|
||||
// Wenn keine Wochen vorhanden
|
||||
if (!weeks || weeks.length === 0) {
|
||||
return res.json({
|
||||
currentOvertime: overtimeOffsetHours,
|
||||
remainingVacation: urlaubstage,
|
||||
totalOvertimeHours: 0,
|
||||
totalOvertimeTaken: 0,
|
||||
totalVacationDays: 0,
|
||||
plannedVacationDays: plannedVacationDays,
|
||||
plannedWeeks: plannedWeeks,
|
||||
urlaubstage: urlaubstage,
|
||||
overtimeOffsetHours: overtimeOffsetHours
|
||||
});
|
||||
}
|
||||
|
||||
let totalOvertimeHours = 0;
|
||||
let totalOvertimeTaken = 0;
|
||||
@@ -246,6 +345,8 @@ function registerUserRoutes(app) {
|
||||
totalOvertimeHours: totalOvertimeHours,
|
||||
totalOvertimeTaken: totalOvertimeTaken,
|
||||
totalVacationDays: totalVacationDays,
|
||||
plannedVacationDays: plannedVacationDays,
|
||||
plannedWeeks: plannedWeeks,
|
||||
urlaubstage: urlaubstage,
|
||||
overtimeOffsetHours: overtimeOffsetHours
|
||||
});
|
||||
@@ -259,11 +360,24 @@ function registerUserRoutes(app) {
|
||||
let weekVacationDays = 0;
|
||||
let weekVacationHours = 0;
|
||||
|
||||
const fullDayHours = wochenstunden > 0 ? wochenstunden / 5 : 8;
|
||||
let fullDayOvertimeDays = 0; // Anzahl Tage mit 8 Überstunden
|
||||
|
||||
entries.forEach(entry => {
|
||||
// Prüfe ob 8 Überstunden (ganzer Tag) eingetragen sind
|
||||
const overtimeValue = entry.overtime_taken_hours ? parseFloat(entry.overtime_taken_hours) : 0;
|
||||
const isFullDayOvertime = overtimeValue > 0 && Math.abs(overtimeValue - fullDayHours) < 0.01;
|
||||
|
||||
if (entry.overtime_taken_hours) {
|
||||
weekOvertimeTaken += entry.overtime_taken_hours;
|
||||
}
|
||||
|
||||
// Wenn 8 Überstunden eingetragen sind, zählt der Tag als 0 Stunden
|
||||
// Diese Tage werden separat gezählt, um die Sollstunden anzupassen
|
||||
if (isFullDayOvertime) {
|
||||
fullDayOvertimeDays++;
|
||||
}
|
||||
|
||||
// Urlaub hat Priorität - wenn Urlaub, zähle nur Urlaubsstunden, nicht zusätzlich Arbeitsstunden
|
||||
if (entry.vacation_type === 'full') {
|
||||
weekVacationDays += 1;
|
||||
@@ -273,12 +387,12 @@ function registerUserRoutes(app) {
|
||||
weekVacationDays += 0.5;
|
||||
weekVacationHours += 4; // Halber Tag = 4 Stunden
|
||||
// Bei halbem Tag Urlaub können noch Arbeitsstunden vorhanden sein
|
||||
if (entry.total_hours) {
|
||||
if (entry.total_hours && !isFullDayOvertime) {
|
||||
weekTotalHours += entry.total_hours;
|
||||
}
|
||||
} else {
|
||||
// Kein Urlaub - zähle nur Arbeitsstunden
|
||||
if (entry.total_hours) {
|
||||
// Kein Urlaub - zähle nur Arbeitsstunden (wenn nicht 8 Überstunden)
|
||||
if (entry.total_hours && !isFullDayOvertime) {
|
||||
weekTotalHours += entry.total_hours;
|
||||
}
|
||||
}
|
||||
@@ -287,11 +401,22 @@ function registerUserRoutes(app) {
|
||||
// Sollstunden berechnen
|
||||
const sollStunden = (wochenstunden / 5) * workdays;
|
||||
|
||||
// Überstunden für diese Woche: Urlaub zählt als normale Arbeitszeit
|
||||
// Überstunden für diese Woche berechnen (wie im Frontend: totalHoursWithVacation - sollStunden)
|
||||
// Wenn 8 Überstunden genommen wurden, zählen diese Tage als 0 Stunden
|
||||
// Die Berechnung: (totalHours + vacationHours) - sollStunden
|
||||
// Bei 8 Überstunden: totalHours = 0, daher: 0 - sollStunden = -sollStunden für diese Woche
|
||||
// Die negativen Stunden (wegen 0 statt Sollstunden) werden durch die verbrauchten Überstunden ausgeglichen
|
||||
// Daher: adjustedSollStunden = sollStunden - (fullDayOvertimeDays * fullDayHours)
|
||||
// So werden die Tage mit 8 Überstunden nicht zu negativen Überstunden führen
|
||||
const weekTotalHoursWithVacation = weekTotalHours + weekVacationHours;
|
||||
const weekOvertimeHours = weekTotalHoursWithVacation - sollStunden;
|
||||
const adjustedSollStunden = sollStunden - (fullDayOvertimeDays * fullDayHours);
|
||||
// weekOvertimeHours = Überstunden diese Woche (wie im Frontend berechnet)
|
||||
const weekOvertimeHours = weekTotalHoursWithVacation - adjustedSollStunden;
|
||||
|
||||
// Kumulativ addieren
|
||||
// WICHTIG: weekOvertimeHours enthält bereits die Überstunden dieser Woche (kann negativ sein bei 8 Überstunden)
|
||||
// weekOvertimeTaken enthält die verbrauchten Überstunden (8 Stunden pro Tag mit 8 Überstunden)
|
||||
// Die aktuellen Überstunden = Summe aller Wochen-Überstunden - verbrauchte Überstunden
|
||||
totalOvertimeHours += weekOvertimeHours;
|
||||
totalOvertimeTaken += weekOvertimeTaken;
|
||||
totalVacationDays += weekVacationDays;
|
||||
@@ -300,6 +425,9 @@ function registerUserRoutes(app) {
|
||||
|
||||
// Wenn alle Wochen verarbeitet wurden, Antwort senden
|
||||
if (processedWeeks === weeks.length && !hasError) {
|
||||
// Aktuelle Überstunden = Summe aller Wochen-Überstunden - verbrauchte Überstunden + Offset
|
||||
// weekOvertimeHours enthält bereits die korrekte Berechnung pro Woche (wie im Frontend)
|
||||
// weekOvertimeTaken enthält die verbrauchten Überstunden (8 Stunden pro Tag mit 8 Überstunden)
|
||||
const currentOvertime = (totalOvertimeHours - totalOvertimeTaken) + overtimeOffsetHours;
|
||||
const remainingVacation = urlaubstage - totalVacationDays;
|
||||
|
||||
@@ -309,6 +437,8 @@ function registerUserRoutes(app) {
|
||||
totalOvertimeHours: totalOvertimeHours,
|
||||
totalOvertimeTaken: totalOvertimeTaken,
|
||||
totalVacationDays: totalVacationDays,
|
||||
plannedVacationDays: plannedVacationDays,
|
||||
plannedWeeks: plannedWeeks,
|
||||
urlaubstage: urlaubstage,
|
||||
overtimeOffsetHours: overtimeOffsetHours
|
||||
});
|
||||
@@ -316,6 +446,7 @@ function registerUserRoutes(app) {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user