'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'; ?>
Track and manage your business expenses and costs.
No data available
Try adjusting your filters or search criteria. Start by recording your first expense.
| Description | Vendor | Category | Amount | Payment | Date | Actions |
|---|---|---|---|---|---|---|
|
•
|
Not specified
|
- |
|
- |
|