// Check-in Server (separater Express-App auf Port 3334) const express = require('express'); const path = require('path'); const { db } = require('./database'); const { getCurrentDate, getCurrentTime, updateTotalHours } = require('./helpers/utils'); const checkinApp = express(); const CHECKIN_PORT = 3334; // View-Engine für Browser-Aufrufe (Bestätigungsseiten) checkinApp.set('view engine', 'ejs'); checkinApp.set('views', path.join(__dirname, 'views')); // Middleware für Check-in-Server checkinApp.use(express.json()); /** Erkennt Browser-Aufruf: Accept-Header enthält text/html (z. B. beim Aufruf per QR/Link im Browser). */ function wantsHtml(req) { const accept = req.get('Accept') || ''; return /text\/html/i.test(accept); } /** Sendet je nach Client entweder HTML-Seite oder JSON. */ function sendResponse(req, res, success, data) { if (wantsHtml(req)) { const title = data.title || (success ? 'Erfolg' : 'Fehler'); const message = data.message || data.error || (success ? 'Aktion erfolgreich.' : 'Ein Fehler ist aufgetreten.'); if (!success && data.status) { res.status(data.status); } res.render('checkin-result', { success, title, message }); } else { if (success) { res.json({ success: true, ...data }); } else { res.status(data.status || 500).json({ success: false, error: data.error }); } } } // API: Check-in (Kommen) checkinApp.get('/api/checkin/:userId', (req, res) => { const userId = parseInt(req.params.userId); const currentDate = getCurrentDate(); const currentTime = getCurrentTime(); // Prüfe ob User existiert db.get('SELECT id FROM users WHERE id = ?', [userId], (err, user) => { if (err || !user) { return sendResponse(req, res, false, { error: 'Benutzer nicht gefunden', status: 404 }); } // Prüfe ob bereits ein Eintrag für heute existiert 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) { return sendResponse(req, res, false, { error: 'Fehler beim Abrufen des Eintrags', status: 500 }); } const successTitle = 'Hallo, du wurdest erfolgreich eingecheckt'; 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) { return sendResponse(req, res, false, { error: 'Fehler beim Erstellen des Eintrags', status: 500 }); } sendResponse(req, res, true, { title: successTitle, message: `Start-Zeit erfasst: ${currentTime}`, start_time: currentTime, date: currentDate }); }); } else if (!entry.start_time) { // Eintrag existiert, aber keine Start-Zeit → Setze start_time db.run('UPDATE timesheet_entries SET start_time = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?', [currentTime, entry.id], (err) => { if (err) { return sendResponse(req, res, false, { error: 'Fehler beim Aktualisieren', status: 500 }); } sendResponse(req, res, true, { title: successTitle, message: `Start-Zeit erfasst: ${currentTime}`, start_time: currentTime, date: currentDate }); }); } else { // Start-Zeit bereits vorhanden → Ignoriere weiteren Check-in sendResponse(req, res, true, { title: successTitle, message: `Bereits eingecheckt um ${entry.start_time}. Check-in ignoriert.`, start_time: entry.start_time, date: currentDate }); } }); }); }); // API: Check-out (Gehen) checkinApp.get('/api/checkout/:userId', (req, res) => { const userId = parseInt(req.params.userId); const currentDate = getCurrentDate(); const currentTime = getCurrentTime(); // Prüfe ob User existiert db.get('SELECT id FROM users WHERE id = ?', [userId], (err, user) => { if (err || !user) { return sendResponse(req, res, false, { error: 'Benutzer nicht gefunden', status: 404 }); } // Prüfe ob bereits ein Eintrag für heute existiert 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) { return sendResponse(req, res, false, { error: 'Fehler beim Abrufen des Eintrags', status: 500 }); } if (!entry || !entry.start_time) { return sendResponse(req, res, false, { error: 'Bitte zuerst einchecken (Kommen).', status: 400 }); } // Berechne total_hours basierend auf start_time, end_time und break_minutes const breakMinutes = entry.break_minutes || 0; const totalHours = updateTotalHours(entry.start_time, currentTime, breakMinutes); // Setze end_time (überschreibt vorherige End-Zeit falls vorhanden) db.run('UPDATE timesheet_entries SET end_time = ?, total_hours = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?', [currentTime, totalHours, entry.id], (err) => { if (err) { return sendResponse(req, res, false, { error: 'Fehler beim Aktualisieren', status: 500 }); } const successTitle = 'Schönen Feierabend, du wurdest erfolgreich ausgecheckt'; const successMessage = `End-Zeit erfasst: ${currentTime}. Gesamtstunden: ${totalHours.toFixed(2)} h`; sendResponse(req, res, true, { title: successTitle, message: successMessage, end_time: currentTime, total_hours: totalHours, date: currentDate }); }); }); }); }); // Check-in-Server starten (auf Port 3334) checkinApp.listen(CHECKIN_PORT, () => { console.log(`Check-in Server läuft auf http://localhost:${CHECKIN_PORT}`); }); module.exports = checkinApp;