// Ping-Service für IP-basierte automatische Zeiterfassung const ping = require('ping'); const { db } = require('../database'); const { getCurrentDate, getCurrentTime, updateTotalHours } = require('../helpers/utils'); // Ping-Funktion für einen User async function pingUserIP(userId, ip, currentDate, currentTime) { try { const result = await ping.promise.probe(ip, { timeout: 3, min_reply: 1 }); const isReachable = result.alive; const now = new Date().toISOString(); // Hole oder erstelle Ping-Status für heute db.get('SELECT * FROM ping_status WHERE user_id = ? AND date = ?', [userId, currentDate], (err, pingStatus) => { if (err) { console.error(`Fehler beim Abrufen des Ping-Status für User ${userId}:`, err); return; } // Hole aktuellen Eintrag für heute db.get('SELECT * FROM timesheet_entries WHERE user_id = ? AND date = ? ORDER BY updated_at DESC, id DESC LIMIT 1', [userId, currentDate], (err, entry) => { if (err) { console.error(`Fehler beim Abrufen des Eintrags für User ${userId}:`, err); return; } if (isReachable) { // IP ist erreichbar if (!pingStatus) { // Erstelle neuen Ping-Status db.run(`INSERT INTO ping_status (user_id, date, last_successful_ping, failed_ping_count, start_time_set) VALUES (?, ?, ?, 0, 0)`, [userId, currentDate, now], (err) => { if (err) console.error(`Fehler beim Erstellen des Ping-Status:`, err); }); } else { // Update Ping-Status: Reset failed_ping_count, update last_successful_ping db.run(`UPDATE ping_status SET last_successful_ping = ?, failed_ping_count = 0, first_failed_ping_time = NULL WHERE user_id = ? AND date = ?`, [now, userId, currentDate], (err) => { if (err) console.error(`Fehler beim Aktualisieren des Ping-Status:`, err); }); } // Start-Zeit setzen wenn noch nicht vorhanden if (entry && !entry.start_time) { db.run('UPDATE timesheet_entries SET start_time = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?', [currentTime, entry.id], (err) => { if (err) { console.error(`Fehler beim Setzen der Start-Zeit für User ${userId}:`, err); } else { console.log(`Start-Zeit gesetzt für User ${userId} um ${currentTime}`); // Markiere dass Start-Zeit gesetzt wurde db.run('UPDATE ping_status SET start_time_set = 1 WHERE user_id = ? AND date = ?', [userId, currentDate], (err) => { if (err) console.error(`Fehler beim Aktualisieren von start_time_set:`, err); }); } }); } else if (!entry) { // Kein Eintrag existiert → Erstelle neuen mit start_time db.run(`INSERT INTO timesheet_entries (user_id, date, start_time, updated_at) VALUES (?, ?, ?, CURRENT_TIMESTAMP)`, [userId, currentDate, currentTime], (err) => { if (err) { console.error(`Fehler beim Erstellen des Eintrags für User ${userId}:`, err); } else { console.log(`Eintrag erstellt und Start-Zeit gesetzt für User ${userId} um ${currentTime}`); // Markiere dass Start-Zeit gesetzt wurde db.run('UPDATE ping_status SET start_time_set = 1 WHERE user_id = ? AND date = ?', [userId, currentDate], (err) => { if (err) { // Falls kein Ping-Status existiert, erstelle einen db.run(`INSERT INTO ping_status (user_id, date, last_successful_ping, failed_ping_count, start_time_set) VALUES (?, ?, ?, 0, 1)`, [userId, currentDate, now], (err) => { if (err) console.error(`Fehler beim Erstellen des Ping-Status:`, err); }); } }); } }); } } else { // IP ist nicht erreichbar if (!pingStatus) { // Erstelle neuen Ping-Status mit failed_ping_count = 1 db.run(`INSERT INTO ping_status (user_id, date, failed_ping_count, first_failed_ping_time) VALUES (?, ?, 1, ?)`, [userId, currentDate, now], (err) => { if (err) console.error(`Fehler beim Erstellen des Ping-Status:`, err); }); } else { // Erhöhe failed_ping_count const newFailedCount = (pingStatus.failed_ping_count || 0) + 1; const firstFailedTime = pingStatus.first_failed_ping_time || now; db.run(`UPDATE ping_status SET failed_ping_count = ?, first_failed_ping_time = ? WHERE user_id = ? AND date = ?`, [newFailedCount, firstFailedTime, userId, currentDate], (err) => { if (err) console.error(`Fehler beim Aktualisieren des Ping-Status:`, err); }); // Wenn 3 oder mehr fehlgeschlagene Pings UND Start-Zeit existiert UND keine End-Zeit if (newFailedCount >= 3 && entry && entry.start_time && !entry.end_time) { // Setze End-Zeit auf Zeit des ersten fehlgeschlagenen Pings const firstFailedDate = new Date(firstFailedTime); const endTime = `${String(firstFailedDate.getHours()).padStart(2, '0')}:${String(firstFailedDate.getMinutes()).padStart(2, '0')}`; // Berechne total_hours const breakMinutes = entry.break_minutes || 0; const totalHours = updateTotalHours(entry.start_time, endTime, breakMinutes); db.run('UPDATE timesheet_entries SET end_time = ?, total_hours = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?', [endTime, totalHours, entry.id], (err) => { if (err) { console.error(`Fehler beim Setzen der End-Zeit für User ${userId}:`, err); } else { console.log(`End-Zeit gesetzt für User ${userId} um ${endTime} (nach ${newFailedCount} fehlgeschlagenen Pings)`); } }); } } } }); }); } catch (error) { console.error(`Fehler beim Ping für User ${userId} (IP: ${ip}):`, error); // Behandle als nicht erreichbar const now = new Date().toISOString(); db.get('SELECT * FROM ping_status WHERE user_id = ? AND date = ?', [userId, currentDate], (err, pingStatus) => { if (!err && pingStatus) { const newFailedCount = (pingStatus.failed_ping_count || 0) + 1; const firstFailedTime = pingStatus.first_failed_ping_time || now; db.run(`UPDATE ping_status SET failed_ping_count = ?, first_failed_ping_time = ? WHERE user_id = ? AND date = ?`, [newFailedCount, firstFailedTime, userId, currentDate], (err) => { if (err) console.error(`Fehler beim Aktualisieren des Ping-Status:`, err); }); } }); } } // Ping-Service Setup function setupPingService() { setInterval(async () => { const currentDate = getCurrentDate(); const currentTime = getCurrentTime(); // Hole alle User mit IP-Adresse db.all('SELECT id, ping_ip FROM users WHERE ping_ip IS NOT NULL AND ping_ip != ""', (err, users) => { if (err) { console.error('Fehler beim Abrufen der User mit IP-Adressen:', err); return; } if (!users || users.length === 0) { return; // Keine User mit IP-Adressen } // Ping alle User parallel users.forEach(user => { pingUserIP(user.id, user.ping_ip, currentDate, currentTime); }); }); }, 60000); // Jede Minute } module.exports = { setupPingService };