'Unauthorized'], 401); } $action = $_GET['action'] ?? ''; $currentUser = getCurrentUser(); try { switch ($action) { case 'revenue_expenses': $data = getRevenueExpensesData(); sendJsonResponse(['success' => true, 'data' => $data]); break; case 'business_segments': $data = getBusinessSegmentsData(); sendJsonResponse(['success' => true, 'data' => $data]); break; case 'monthly_trends': $year = $_GET['year'] ?? date('Y'); $data = getMonthlyTrendsData($year); sendJsonResponse(['success' => true, 'data' => $data]); break; case 'cash_flow': $data = getCashFlowData(); sendJsonResponse(['success' => true, 'data' => $data]); break; case 'top_products': $data = getTopProductsData(); sendJsonResponse(['success' => true, 'data' => $data]); break; case 'dashboard_stats': $data = getDashboardStatsData(); sendJsonResponse(['success' => true, 'data' => $data]); break; default: sendJsonResponse(['error' => 'Invalid action'], 400); } } catch (Exception $e) { error_log('Dashboard API Error: ' . $e->getMessage()); sendJsonResponse(['error' => 'Internal server error'], 500); } /** * Get revenue vs expenses data for chart */ function getRevenueExpensesData() { $period = $_GET['period'] ?? 'year'; $currentUser = getCurrentUser(); // Determine date range based on period switch ($period) { case 'month': $startDate = date('Y-m-01'); $endDate = date('Y-m-t'); $groupBy = 'DAY'; $dateFormat = '%Y-%m-%d'; break; case 'quarter': $startDate = date('Y-m-01', strtotime('first day of -2 months')); $endDate = date('Y-m-t'); $groupBy = 'WEEK'; $dateFormat = '%Y-%u'; break; default: // year $startDate = date('Y-01-01'); $endDate = date('Y-12-31'); $groupBy = 'MONTH'; $dateFormat = '%Y-%m'; } // Base conditions for user filtering $userCondition = ''; $params = [$startDate, $endDate]; if ($currentUser['role'] !== 'admin') { $userCondition = ' AND created_by = ?'; $params[] = $currentUser['id']; } // Get revenue data $revenueQuery = " SELECT DATE_FORMAT(sale_date, '{$dateFormat}') as period, SUM(amount) as amount FROM sales WHERE sale_date BETWEEN ? AND ? {$userCondition} GROUP BY DATE_FORMAT(sale_date, '{$dateFormat}') ORDER BY period "; $revenueData = fetchAll($revenueQuery, $params); // Get expenses data $expensesQuery = " SELECT DATE_FORMAT(expense_date, '{$dateFormat}') as period, SUM(amount) as amount FROM expenses WHERE expense_date BETWEEN ? AND ? {$userCondition} GROUP BY DATE_FORMAT(expense_date, '{$dateFormat}') ORDER BY period "; $expensesData = fetchAll($expensesQuery, $params); // Combine and format data for Chart.js $periods = array_unique(array_merge( array_column($revenueData, 'period'), array_column($expensesData, 'period') )); sort($periods); $revenue = []; $expenses = []; $labels = []; foreach ($periods as $period) { $revenueAmount = 0; $expenseAmount = 0; foreach ($revenueData as $row) { if ($row['period'] === $period) { $revenueAmount = (float)$row['amount']; break; } } foreach ($expensesData as $row) { if ($row['period'] === $period) { $expenseAmount = (float)$row['amount']; break; } } $revenue[] = $revenueAmount; $expenses[] = $expenseAmount; // Format label based on period if ($period === 'month') { $labels[] = date('M j', strtotime($period)); } elseif ($period === 'quarter') { $labels[] = 'Week ' . date('W', strtotime($period . '-01')); } else { $labels[] = date('M Y', strtotime($period . '-01')); } } return [ 'labels' => $labels, 'datasets' => [ [ 'label' => 'Revenue', 'data' => $revenue, 'backgroundColor' => 'rgba(255, 193, 7, 0.2)', 'borderColor' => 'rgba(255, 193, 7, 1)', 'borderWidth' => 2, 'fill' => true ], [ 'label' => 'Expenses', 'data' => $expenses, 'backgroundColor' => 'rgba(220, 53, 69, 0.2)', 'borderColor' => 'rgba(220, 53, 69, 1)', 'borderWidth' => 2, 'fill' => true ] ] ]; } /** * Get business segments data for pie chart */ function getBusinessSegmentsData() { $currentUser = getCurrentUser(); $userCondition = ''; $params = []; if ($currentUser['role'] !== 'admin') { $userCondition = ' AND s.created_by = ?'; $params[] = $currentUser['id']; } $query = " SELECT bs.name as segment_name, COALESCE(SUM(s.amount), 0) as revenue FROM business_segments bs LEFT JOIN sales s ON bs.id = s.segment_id {$userCondition} WHERE bs.status = 'active' GROUP BY bs.id, bs.name HAVING revenue > 0 ORDER BY revenue DESC "; $data = fetchAll($query, $params); $labels = array_column($data, 'segment_name'); $amounts = array_map(function($row) { return (float)$row['revenue']; }, $data); $colors = [ 'rgba(30, 58, 95, 1)', // Primary Navy 'rgba(255, 193, 7, 1)', // Yellow 'rgba(40, 167, 69, 1)', // Success 'rgba(23, 162, 184, 1)', // Info 'rgba(220, 53, 69, 1)' // Danger ]; return [ 'labels' => $labels, 'datasets' => [ [ 'data' => $amounts, 'backgroundColor' => array_slice($colors, 0, count($labels)), 'borderColor' => '#fff', 'borderWidth' => 2 ] ] ]; } /** * Get monthly trends data */ function getMonthlyTrendsData($year) { $currentUser = getCurrentUser(); $userCondition = ''; $params = [$year]; if ($currentUser['role'] !== 'admin') { $userCondition = ' AND created_by = ?'; $params[] = $currentUser['id']; } $query = " SELECT MONTH(transaction_date) as month, MONTHNAME(transaction_date) as month_name, SUM(CASE WHEN type = 'revenue' THEN amount ELSE 0 END) as revenue, SUM(CASE WHEN type = 'expense' THEN amount ELSE 0 END) as expenses FROM ( SELECT 'revenue' as type, amount, sale_date as transaction_date, created_by FROM sales UNION ALL SELECT 'expense' as type, amount, expense_date as transaction_date, created_by FROM expenses ) t WHERE YEAR(transaction_date) = ? {$userCondition} GROUP BY MONTH(transaction_date), MONTHNAME(transaction_date) ORDER BY MONTH(transaction_date) "; $data = fetchAll($query, $params); // Fill in missing months with zeros $months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']; $revenue = array_fill(0, 12, 0); $expenses = array_fill(0, 12, 0); foreach ($data as $row) { $monthIndex = (int)$row['month'] - 1; $revenue[$monthIndex] = (float)$row['revenue']; $expenses[$monthIndex] = (float)$row['expenses']; } return [ 'labels' => $months, 'datasets' => [ [ 'label' => 'Revenue', 'data' => $revenue, 'borderColor' => 'rgba(30, 58, 95, 1)', 'backgroundColor' => 'rgba(30, 58, 95, 0.1)', 'tension' => 0.4, 'fill' => true ], [ 'label' => 'Profit', 'data' => array_map(function($r, $e) { return $r - $e; }, $revenue, $expenses), 'borderColor' => 'rgba(40, 167, 69, 1)', 'backgroundColor' => 'rgba(40, 167, 69, 0.1)', 'tension' => 0.4, 'fill' => true ] ] ]; } /** * Get cash flow data for bar chart */ function getCashFlowData() { $currentUser = getCurrentUser(); $userCondition = ''; $params = []; if ($currentUser['role'] !== 'admin') { $userCondition = ' AND created_by = ?'; $params[] = $currentUser['id']; } // Get last 4 weeks of data $query = " SELECT WEEK(transaction_date) as week_num, SUM(CASE WHEN type = 'revenue' THEN amount ELSE -amount END) as net_flow FROM ( SELECT 'revenue' as type, amount, sale_date as transaction_date, created_by FROM sales WHERE sale_date >= DATE_SUB(CURDATE(), INTERVAL 4 WEEK) UNION ALL SELECT 'expense' as type, amount, expense_date as transaction_date, created_by FROM expenses WHERE expense_date >= DATE_SUB(CURDATE(), INTERVAL 4 WEEK) ) t WHERE 1=1 {$userCondition} GROUP BY WEEK(transaction_date) ORDER BY WEEK(transaction_date) DESC LIMIT 4 "; $data = fetchAll($query, $params); $data = array_reverse($data); // Show oldest to newest $labels = []; $cashFlow = []; $colors = []; for ($i = 0; $i < count($data); $i++) { $labels[] = 'Week ' . ($i + 1); $amount = (float)$data[$i]['net_flow']; $cashFlow[] = $amount; $colors[] = $amount >= 0 ? 'rgba(40, 167, 69, 1)' : 'rgba(220, 53, 69, 1)'; } return [ 'labels' => $labels, 'datasets' => [ [ 'label' => 'Net Cash Flow', 'data' => $cashFlow, 'backgroundColor' => $colors, 'borderColor' => $colors, 'borderWidth' => 1 ] ] ]; } /** * Get top products/services data */ function getTopProductsData() { $currentUser = getCurrentUser(); $userCondition = ''; $params = []; if ($currentUser['role'] !== 'admin') { $userCondition = ' AND created_by = ?'; $params[] = $currentUser['id']; } $query = " SELECT title, SUM(amount) as total_revenue, COUNT(*) as sales_count FROM sales WHERE sale_date >= DATE_SUB(CURDATE(), INTERVAL 30 DAY) {$userCondition} GROUP BY title ORDER BY total_revenue DESC LIMIT 5 "; $data = fetchAll($query, $params); $labels = array_column($data, 'title'); $revenues = array_map(function($row) { return (float)$row['total_revenue']; }, $data); $colors = [ 'rgba(30, 58, 95, 1)', 'rgba(255, 193, 7, 1)', 'rgba(40, 167, 69, 1)', 'rgba(23, 162, 184, 1)', 'rgba(220, 53, 69, 1)' ]; return [ 'labels' => $labels, 'datasets' => [ [ 'label' => 'Revenue', 'data' => $revenues, 'backgroundColor' => array_slice($colors, 0, count($labels)), 'borderColor' => '#fff', 'borderWidth' => 1 ] ] ]; } /** * Get dashboard statistics summary */ function getDashboardStatsData() { $currentUser = getCurrentUser(); $stats = getDashboardStats($currentUser['role'] !== 'admin' ? $currentUser['id'] : null); // Calculate growth rates (mock data for now - implement actual calculation) $growthRates = [ 'revenue_growth' => 12.5, 'expense_growth' => -5.2, 'profit_growth' => 18.3, 'transaction_growth' => 8.1 ]; return array_merge($stats, $growthRates); } ?>