'Expense Management'] ]; $success = ''; $error = ''; $currentUser = getCurrentUser(); // Handle form submissions if ($_SERVER['REQUEST_METHOD'] === 'POST') { try { $action = $_POST['action'] ?? ''; switch ($action) { case 'add_expense': $title = sanitizeInput($_POST['title']); $amount = (float)$_POST['amount']; $categoryId = !empty($_POST['category_id']) ? (int)$_POST['category_id'] : null; $segmentId = !empty($_POST['segment_id']) ? (int)$_POST['segment_id'] : null; $expenseDate = $_POST['expense_date']; $description = sanitizeInput($_POST['description'] ?? ''); $paymentMethod = sanitizeInput($_POST['payment_method'] ?? ''); $vendor = sanitizeInput($_POST['vendor'] ?? ''); // Validation if (empty($title) || $amount <= 0 || empty($expenseDate)) { throw new Exception('Title, amount, and expense date are required.'); } // Handle receipt image upload $receiptImage = null; if (isset($_FILES['receipt_image']) && $_FILES['receipt_image']['error'] === UPLOAD_ERR_OK) { try { $receiptImage = handleFileUpload('receipt_image', '../uploads/receipts/'); } catch (Exception $e) { // Log error but don't fail the transaction error_log("Receipt upload failed: " . $e->getMessage()); } } $expenseData = [ 'title' => $title, 'amount' => $amount, 'category_id' => $categoryId, 'segment_id' => $segmentId, 'expense_date' => $expenseDate, 'description' => $description, 'payment_method' => $paymentMethod, 'vendor' => $vendor, 'receipt_image' => $receiptImage, 'created_by' => $currentUser['id'], 'created_at' => date('Y-m-d H:i:s') ]; $expenseId = insertData('expenses', $expenseData); if ($expenseId) { logSystemActivity('Add Expense', "Added expense: {$title} - " . formatIndianCurrency($amount)); $success = 'Expense recorded successfully!'; } else { throw new Exception('Failed to record expense.'); } break; case 'update_expense': $expenseId = (int)$_POST['expense_id']; $title = sanitizeInput($_POST['title']); $amount = (float)$_POST['amount']; $categoryId = !empty($_POST['category_id']) ? (int)$_POST['category_id'] : null; $segmentId = !empty($_POST['segment_id']) ? (int)$_POST['segment_id'] : null; $expenseDate = $_POST['expense_date']; $description = sanitizeInput($_POST['description'] ?? ''); $paymentMethod = sanitizeInput($_POST['payment_method'] ?? ''); $vendor = sanitizeInput($_POST['vendor'] ?? ''); // Validation if (empty($title) || $amount <= 0 || empty($expenseDate)) { throw new Exception('Title, amount, and expense date are required.'); } // Check if user can edit this expense $existingExpense = fetchRow("SELECT * FROM expenses WHERE id = ?", [$expenseId]); if (!$existingExpense) { throw new Exception('Expense not found.'); } if ($currentUser['role'] !== 'admin' && $existingExpense['created_by'] != $currentUser['id']) { throw new Exception('You can only edit your own expense records.'); } $updateData = [ 'title' => $title, 'amount' => $amount, 'category_id' => $categoryId, 'segment_id' => $segmentId, 'expense_date' => $expenseDate, 'description' => $description, 'payment_method' => $paymentMethod, 'vendor' => $vendor ]; updateData('expenses', $updateData, 'id = ?', [$expenseId]); logSystemActivity('Update Expense', "Updated expense ID: {$expenseId}"); $success = 'Expense updated successfully!'; break; case 'delete_expense': $expenseId = (int)$_POST['expense_id']; // Check if user can delete this expense $existingExpense = fetchRow("SELECT * FROM expenses WHERE id = ?", [$expenseId]); if (!$existingExpense) { throw new Exception('Expense not found.'); } if ($currentUser['role'] !== 'admin' && $existingExpense['created_by'] != $currentUser['id']) { throw new Exception('You can only delete your own expense records.'); } // Delete associated receipt image if ($existingExpense['receipt_image'] && file_exists('../' . $existingExpense['receipt_image'])) { unlink('../' . $existingExpense['receipt_image']); } executeQuery("DELETE FROM expenses WHERE id = ?", [$expenseId]); logSystemActivity('Delete Expense', "Deleted expense: {$existingExpense['title']}"); $success = 'Expense deleted successfully!'; break; } } catch (Exception $e) { $error = $e->getMessage(); } } // Get filter parameters $dateFrom = $_GET['date_from'] ?? date('Y-m-01'); // First day of current month $dateTo = $_GET['date_to'] ?? date('Y-m-d'); // Today $segmentFilter = $_GET['segment'] ?? ''; $categoryFilter = $_GET['category'] ?? ''; $search = $_GET['search'] ?? ''; // Build query for expenses list $whereConditions = []; $params = []; // Date range filter if ($dateFrom) { $whereConditions[] = "e.expense_date >= ?"; $params[] = $dateFrom; } if ($dateTo) { $whereConditions[] = "e.expense_date <= ?"; $params[] = $dateTo; } // Segment filter if ($segmentFilter) { $whereConditions[] = "e.segment_id = ?"; $params[] = $segmentFilter; } // Category filter if ($categoryFilter) { $whereConditions[] = "e.category_id = ?"; $params[] = $categoryFilter; } // Search filter if ($search) { $whereConditions[] = "(e.title LIKE ? OR e.vendor LIKE ? OR e.description LIKE ?)"; $params[] = "%$search%"; $params[] = "%$search%"; $params[] = "%$search%"; } // User-specific filter for non-admin users if ($currentUser['role'] !== 'admin' && !hasPermission('manage_expenses')) { $whereConditions[] = "e.created_by = ?"; $params[] = $currentUser['id']; } $whereClause = !empty($whereConditions) ? 'WHERE ' . implode(' AND ', $whereConditions) : ''; // Get expenses with related data $expensesQuery = " SELECT e.*, bs.name as segment_name, c.name as category_name, u.full_name as created_by_name FROM expenses e LEFT JOIN business_segments bs ON e.segment_id = bs.id LEFT JOIN categories c ON e.category_id = c.id LEFT JOIN users u ON e.created_by = u.id {$whereClause} ORDER BY e.expense_date DESC, e.created_at DESC LIMIT 100 "; $expenses = fetchAll($expensesQuery, $params); // Calculate totals for the filtered data $totalQuery = " SELECT COUNT(*) as total_count, SUM(amount) as total_amount, AVG(amount) as avg_amount FROM expenses e {$whereClause} "; $totals = fetchRow($totalQuery, $params); // Get expense breakdown by category $categoryBreakdown = fetchAll(" SELECT c.name as category_name, SUM(e.amount) as total_amount, COUNT(e.id) as count FROM expenses e LEFT JOIN categories c ON e.category_id = c.id {$whereClause} GROUP BY e.category_id, c.name ORDER BY total_amount DESC LIMIT 10 ", $params); // Get data for dropdowns $businessSegments = getBusinessSegments(); $expenseCategories = getCategories('expense'); include '../includes/header.php'; ?>
Total Expenses
Transactions
Average Expense
Top Categories

No data available

0 ? ($category['total_amount'] / $totals['total_amount']) * 100 : 0; ?>
Clear
Expense Records
Showing of expenses
No Expenses Found

Try adjusting your filters or search criteria. Start by recording your first expense.

Description Vendor Category Amount Payment Date Actions
Not specified
-
-