import express from 'express'; import db from '../config/database.js'; import { authenticateToken, authorize } from '../middleware/auth.js'; const router = express.Router(); // Get all attendance records router.get('/', authenticateToken, async (req, res) => { try { const { employeeId, startDate, endDate, status } = req.query; let query = ` SELECT a.*, e.name as employee_name, e.username as employee_username, s.name as supervisor_name, d.name as department_name, c.name as contractor_name FROM attendance a JOIN users e ON a.employee_id = e.id JOIN users s ON a.supervisor_id = s.id LEFT JOIN departments d ON e.department_id = d.id LEFT JOIN users c ON e.contractor_id = c.id WHERE 1=1 `; const params = []; // Role-based filtering if (req.user.role === 'Supervisor') { query += ' AND a.supervisor_id = ?'; params.push(req.user.id); } else if (req.user.role === 'Employee') { query += ' AND a.employee_id = ?'; params.push(req.user.id); } if (employeeId) { query += ' AND a.employee_id = ?'; params.push(employeeId); } if (startDate) { query += ' AND a.work_date >= ?'; params.push(startDate); } if (endDate) { query += ' AND a.work_date <= ?'; params.push(endDate); } if (status) { query += ' AND a.status = ?'; params.push(status); } query += ' ORDER BY a.work_date DESC, a.check_in_time DESC'; const [records] = await db.query(query, params); res.json(records); } catch (error) { console.error('Get attendance error:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Get attendance by ID router.get('/:id', authenticateToken, async (req, res) => { try { const [records] = await db.query( `SELECT a.*, e.name as employee_name, e.username as employee_username, s.name as supervisor_name, d.name as department_name, c.name as contractor_name FROM attendance a JOIN users e ON a.employee_id = e.id JOIN users s ON a.supervisor_id = s.id LEFT JOIN departments d ON e.department_id = d.id LEFT JOIN users c ON e.contractor_id = c.id WHERE a.id = ?`, [req.params.id] ); if (records.length === 0) { return res.status(404).json({ error: 'Attendance record not found' }); } res.json(records[0]); } catch (error) { console.error('Get attendance error:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Check in employee (Supervisor or SuperAdmin) router.post('/check-in', authenticateToken, authorize('Supervisor', 'SuperAdmin'), async (req, res) => { try { const { employeeId, workDate } = req.body; if (!employeeId || !workDate) { return res.status(400).json({ error: 'Employee ID and work date required' }); } // Verify employee exists (SuperAdmin can check in any employee, Supervisor only their department) let employeeQuery = 'SELECT * FROM users WHERE id = ? AND role = ?'; let employeeParams = [employeeId, 'Employee']; if (req.user.role === 'Supervisor') { employeeQuery += ' AND department_id = ?'; employeeParams.push(req.user.departmentId); } const [employees] = await db.query(employeeQuery, employeeParams); if (employees.length === 0) { return res.status(403).json({ error: 'Employee not found or not in your department' }); } // Check if already checked in today const [existing] = await db.query( 'SELECT * FROM attendance WHERE employee_id = ? AND work_date = ? AND status = ?', [employeeId, workDate, 'CheckedIn'] ); if (existing.length > 0) { return res.status(400).json({ error: 'Employee already checked in today' }); } const checkInTime = new Date(); const [result] = await db.query( 'INSERT INTO attendance (employee_id, supervisor_id, check_in_time, work_date, status) VALUES (?, ?, ?, ?, ?)', [employeeId, req.user.id, checkInTime, workDate, 'CheckedIn'] ); const [newRecord] = await db.query( `SELECT a.*, e.name as employee_name, e.username as employee_username, s.name as supervisor_name, d.name as department_name, c.name as contractor_name FROM attendance a JOIN users e ON a.employee_id = e.id JOIN users s ON a.supervisor_id = s.id LEFT JOIN departments d ON e.department_id = d.id LEFT JOIN users c ON e.contractor_id = c.id WHERE a.id = ?`, [result.insertId] ); res.status(201).json(newRecord[0]); } catch (error) { console.error('Check in error:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Check out employee (Supervisor or SuperAdmin) router.post('/check-out', authenticateToken, authorize('Supervisor', 'SuperAdmin'), async (req, res) => { try { const { employeeId, workDate } = req.body; if (!employeeId || !workDate) { return res.status(400).json({ error: 'Employee ID and work date required' }); } // Find the check-in record (SuperAdmin can check out any, Supervisor only their own) let query = 'SELECT * FROM attendance WHERE employee_id = ? AND work_date = ? AND status = ?'; let params = [employeeId, workDate, 'CheckedIn']; if (req.user.role === 'Supervisor') { query += ' AND supervisor_id = ?'; params.push(req.user.id); } const [records] = await db.query(query, params); if (records.length === 0) { return res.status(404).json({ error: 'No check-in record found for today' }); } const checkOutTime = new Date(); await db.query( 'UPDATE attendance SET check_out_time = ?, status = ? WHERE id = ?', [checkOutTime, 'CheckedOut', records[0].id] ); const [updatedRecord] = await db.query( `SELECT a.*, e.name as employee_name, e.username as employee_username, s.name as supervisor_name, d.name as department_name, c.name as contractor_name FROM attendance a JOIN users e ON a.employee_id = e.id JOIN users s ON a.supervisor_id = s.id LEFT JOIN departments d ON e.department_id = d.id LEFT JOIN users c ON e.contractor_id = c.id WHERE a.id = ?`, [records[0].id] ); res.json(updatedRecord[0]); } catch (error) { console.error('Check out error:', error); res.status(500).json({ error: 'Internal server error' }); } }); // Get attendance summary router.get('/summary/stats', authenticateToken, async (req, res) => { try { const { startDate, endDate, departmentId } = req.query; let query = ` SELECT COUNT(DISTINCT a.employee_id) as total_employees, COUNT(DISTINCT CASE WHEN a.status = 'CheckedIn' THEN a.employee_id END) as checked_in, COUNT(DISTINCT CASE WHEN a.status = 'CheckedOut' THEN a.employee_id END) as checked_out, d.name as department_name FROM attendance a JOIN users e ON a.employee_id = e.id LEFT JOIN departments d ON e.department_id = d.id WHERE 1=1 `; const params = []; if (req.user.role === 'Supervisor') { query += ' AND a.supervisor_id = ?'; params.push(req.user.id); } if (startDate) { query += ' AND a.work_date >= ?'; params.push(startDate); } if (endDate) { query += ' AND a.work_date <= ?'; params.push(endDate); } if (departmentId) { query += ' AND e.department_id = ?'; params.push(departmentId); } query += ' GROUP BY d.id, d.name'; const [summary] = await db.query(query, params); res.json(summary); } catch (error) { console.error('Get attendance summary error:', error); res.status(500).json({ error: 'Internal server error' }); } }); export default router;