prepare(" SELECT id FROM attendance WHERE user_id = ? AND departure_time IS NULL AND (leave_type IS NULL OR leave_type = 'work') ORDER BY created_at DESC LIMIT 1 "); $stmt->execute([$userId]); $result['my_shift'] = [ 'has_ongoing' => (bool) $stmt->fetch(), ]; } // --- Docházka dnes (attendance.admin) --- if (hasPermission($authData, 'attendance.admin')) { // Poslední pracovní záznam per uživatel (vyloučit ty co mají leave dnes) $stmt = $pdo->query(" SELECT u.id, CONCAT(u.first_name, ' ', u.last_name) as name, CONCAT(LEFT(u.first_name, 1), LEFT(u.last_name, 1)) as initials, a.arrival_time, a.departure_time, a.break_start, a.break_end FROM users u LEFT JOIN ( SELECT a1.* FROM attendance a1 INNER JOIN ( SELECT user_id, MAX(id) as max_id FROM attendance WHERE shift_date = CURDATE() AND (leave_type IS NULL OR leave_type = 'work') GROUP BY user_id ) a2 ON a1.id = a2.max_id ) a ON u.id = a.user_id WHERE u.is_active = 1 AND u.id NOT IN ( SELECT user_id FROM attendance WHERE shift_date = CURDATE() AND leave_type IN ('vacation', 'sick', 'holiday', 'unpaid') ) ORDER BY a.arrival_time IS NULL, a.arrival_time ASC "); $users = $stmt->fetchAll(); $present = 0; $away = 0; $attendanceUsers = []; foreach ($users as $u) { $status = 'out'; $arrivedAt = null; if ($u['arrival_time'] !== null) { if ($u['departure_time'] !== null) { $status = 'out'; } elseif ($u['break_start'] !== null && $u['break_end'] === null) { $status = 'away'; $away++; } else { $status = 'in'; $present++; } $arrivedAt = date('H:i', strtotime($u['arrival_time'])); } $attendanceUsers[] = [ 'name' => $u['name'], 'initials' => $u['initials'], 'status' => $status, 'arrived_at' => $arrivedAt, ]; } // Dnes na dovolene/nemocenske $stmtLeave = $pdo->query(" SELECT CONCAT(u.first_name, ' ', u.last_name) as name, CONCAT(LEFT(u.first_name, 1), LEFT(u.last_name, 1)) as initials, a.leave_type FROM attendance a JOIN users u ON a.user_id = u.id WHERE a.shift_date = CURDATE() AND a.leave_type IN ('vacation', 'sick', 'holiday', 'unpaid') "); $onLeave = $stmtLeave->fetchAll(); foreach ($onLeave as $leave) { $attendanceUsers[] = [ 'name' => $leave['name'], 'initials' => $leave['initials'], 'status' => 'leave', 'arrived_at' => null, 'leave_type' => $leave['leave_type'], ]; } $result['attendance'] = [ 'present_today' => $present, 'away_today' => $away, 'total_active' => count($users), 'on_leave' => count($onLeave), 'users' => $attendanceUsers, ]; } // --- Nabídky (offers.view) --- if (hasPermission($authData, 'offers.view')) { $stmt = $pdo->query(" SELECT COUNT(*) as total, SUM(CASE WHEN q.order_id IS NULL AND (q.valid_until IS NULL OR q.valid_until >= CURDATE()) THEN 1 ELSE 0 END) as open_count, SUM(CASE WHEN q.order_id IS NULL AND q.valid_until < CURDATE() THEN 1 ELSE 0 END) as expired_count, SUM(CASE WHEN q.order_id IS NOT NULL THEN 1 ELSE 0 END) as converted_count FROM quotations q "); $counts = $stmt->fetch(); $stmtMonth = $pdo->query(" SELECT COUNT(*) as count FROM quotations WHERE YEAR(created_at) = YEAR(CURDATE()) AND MONTH(created_at) = MONTH(CURDATE()) "); $monthData = $stmtMonth->fetch(); $result['offers'] = [ 'total' => (int) $counts['total'], 'open_count' => (int) $counts['open_count'], 'expired_count' => (int) $counts['expired_count'], 'converted_count' => (int) $counts['converted_count'], 'created_this_month' => (int) $monthData['count'], ]; } // --- Projekty (projects.view) --- if (hasPermission($authData, 'projects.view')) { $stmt = $pdo->query(" SELECT p.id, p.name, p.status, c.name as customer_name FROM projects p LEFT JOIN customers c ON p.customer_id = c.id WHERE p.status = 'aktivni' ORDER BY p.modified_at DESC LIMIT 5 "); $activeProjects = $stmt->fetchAll(); $stmtCounts = $pdo->query(" SELECT SUM(CASE WHEN status = 'aktivni' THEN 1 ELSE 0 END) as active_count, SUM(CASE WHEN status = 'dokonceny' THEN 1 ELSE 0 END) as completed_count FROM projects WHERE status != 'deleted' "); $projectCounts = $stmtCounts->fetch(); $result['projects'] = [ 'active_count' => (int) ($projectCounts['active_count'] ?? 0), 'completed_count' => (int) ($projectCounts['completed_count'] ?? 0), 'active_projects' => $activeProjects, ]; } // --- Faktury (invoices.view) --- if (hasPermission($authData, 'invoices.view')) { $stmt = $pdo->query(" SELECT COUNT(*) as total, SUM(CASE WHEN i.status = 'paid' AND YEAR(i.paid_date) = YEAR(CURDATE()) AND MONTH(i.paid_date) = MONTH(CURDATE()) THEN 1 ELSE 0 END) as paid_this_month, SUM(CASE WHEN i.status IN ('issued', 'overdue') THEN 1 ELSE 0 END) as unpaid_count FROM invoices i "); $invCounts = $stmt->fetch(); // Tržby tento měsíc per faktura (pro kurz k datu vystaveni) $stmtRevenue = $pdo->query(" SELECT i.id, i.currency, i.issue_date, COALESCE(SUM(ii.quantity * ii.unit_price), 0) as revenue FROM invoices i JOIN invoice_items ii ON i.id = ii.invoice_id WHERE i.status = 'paid' AND YEAR(i.paid_date) = YEAR(CURDATE()) AND MONTH(i.paid_date) = MONTH(CURDATE()) GROUP BY i.id, i.currency, i.issue_date ORDER BY revenue DESC "); $revByCurrency = []; $revCzkItems = []; foreach ($stmtRevenue->fetchAll() as $row) { $cur = $row['currency']; $amt = (float) $row['revenue']; $revByCurrency[$cur] = ($revByCurrency[$cur] ?? 0) + $amt; $revCzkItems[] = [ 'amount' => $amt, 'currency' => $cur, 'date' => $row['issue_date'], ]; } $revenueByCurrency = []; foreach ($revByCurrency as $cur => $total) { $revenueByCurrency[] = [ 'currency' => $cur, 'amount' => round($total, 2), ]; } $cnb = CnbRates::getInstance(); $result['invoices'] = [ 'total' => (int) $invCounts['total'], 'paid_this_month' => (int) $invCounts['paid_this_month'], 'unpaid_count' => (int) $invCounts['unpaid_count'], 'revenue_this_month' => $revenueByCurrency, 'revenue_czk' => $cnb->sumToCzk($revCzkItems), ]; } // --- Čekající žádosti (attendance.approve) --- if (hasPermission($authData, 'attendance.approve')) { $stmt = $pdo->query(" SELECT COUNT(*) as count FROM leave_requests WHERE status = 'pending' "); $pending = $stmt->fetch(); $result['leave_pending'] = [ 'count' => (int) $pending['count'], ]; } // --- Poslední aktivita (settings.roles = admin přehled) --- if (hasPermission($authData, 'settings.roles')) { $stmt = $pdo->query(" SELECT username, action, entity_type, description, created_at FROM audit_logs WHERE action IN ('create', 'update', 'delete', 'login') ORDER BY created_at DESC LIMIT 8 "); $result['recent_activity'] = $stmt->fetchAll(); } jsonResponse($result);