v4 add expenses

This commit is contained in:
Flatlogic Bot 2026-02-17 09:09:05 +00:00
parent 7788a6a03f
commit 01b6fa4c64

456
index.php
View File

@ -107,6 +107,72 @@ if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action'])) {
}
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
// --- Expense Categories Handlers ---
if (isset($_POST['add_expense_category'])) {
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
if ($name_en && $name_ar) {
$stmt = db()->prepare("INSERT INTO expense_categories (name_en, name_ar) VALUES (?, ?)");
$stmt->execute([$name_en, $name_ar]);
$message = "Expense Category added successfully!";
}
}
if (isset($_POST['edit_expense_category'])) {
$id = (int)$_POST['id'];
$name_en = $_POST['name_en'] ?? '';
$name_ar = $_POST['name_ar'] ?? '';
if ($id && $name_en && $name_ar) {
$stmt = db()->prepare("UPDATE expense_categories SET name_en = ?, name_ar = ? WHERE id = ?");
$stmt->execute([$name_en, $name_ar, $id]);
$message = "Expense Category updated successfully!";
}
}
if (isset($_POST['delete_expense_category'])) {
$id = (int)$_POST['id'];
if ($id) {
$stmt = db()->prepare("DELETE FROM expense_categories WHERE id = ?");
$stmt->execute([$id]);
$message = "Expense Category deleted successfully!";
}
}
// --- Expenses Handlers ---
if (isset($_POST['add_expense'])) {
$category_id = (int)$_POST['category_id'];
$amount = (float)$_POST['amount'];
$date = $_POST['expense_date'] ?: date('Y-m-d');
$desc = $_POST['description'] ?? '';
$ref = $_POST['reference_no'] ?? '';
if ($category_id && $amount > 0) {
$stmt = db()->prepare("INSERT INTO expenses (category_id, amount, expense_date, description, reference_no) VALUES (?, ?, ?, ?, ?)");
$stmt->execute([$category_id, $amount, $date, $desc, $ref]);
$message = "Expense recorded successfully!";
}
}
if (isset($_POST['edit_expense'])) {
$id = (int)$_POST['id'];
$category_id = (int)$_POST['category_id'];
$amount = (float)$_POST['amount'];
$date = $_POST['expense_date'] ?: date('Y-m-d');
$desc = $_POST['description'] ?? '';
$ref = $_POST['reference_no'] ?? '';
if ($id && $category_id && $amount > 0) {
$stmt = db()->prepare("UPDATE expenses SET category_id = ?, amount = ?, expense_date = ?, description = ?, reference_no = ? WHERE id = ?");
$stmt->execute([$category_id, $amount, $date, $desc, $ref, $id]);
$message = "Expense updated successfully!";
}
}
if (isset($_POST['delete_expense'])) {
$id = (int)$_POST['id'];
if ($id) {
$stmt = db()->prepare("DELETE FROM expenses WHERE id = ?");
$stmt->execute([$id]);
$message = "Expense deleted successfully!";
}
}
if (isset($_POST['add_customer'])) {
$name = $_POST['name'] ?? '';
$email = $_POST['email'] ?? '';
@ -1224,6 +1290,51 @@ switch ($page) {
$data['transactions'] = $transactions;
}
break;
case 'expense_categories':
$data['expense_categories'] = db()->query("SELECT * FROM expense_categories ORDER BY name_en ASC")->fetchAll();
break;
case 'expenses':
$where = ["1=1"];
$params = [];
if (!empty($_GET['category_id'])) {
$where[] = "e.category_id = ?";
$params[] = $_GET['category_id'];
}
if (!empty($_GET['start_date'])) {
$where[] = "e.expense_date >= ?";
$params[] = $_GET['start_date'];
}
if (!empty($_GET['end_date'])) {
$where[] = "e.expense_date <= ?";
$params[] = $_GET['end_date'];
}
$whereSql = implode(" AND ", $where);
$stmt = db()->prepare("SELECT e.*, c.name_en as cat_en, c.name_ar as cat_ar
FROM expenses e
LEFT JOIN expense_categories c ON e.category_id = c.id
WHERE $whereSql
ORDER BY e.expense_date DESC, e.id DESC");
$stmt->execute($params);
$data['expenses'] = $stmt->fetchAll();
$data['expense_categories'] = db()->query("SELECT * FROM expense_categories ORDER BY name_en ASC")->fetchAll();
break;
case 'expense_report':
$start_date = $_GET['start_date'] ?? date('Y-m-01');
$end_date = $_GET['end_date'] ?? date('Y-m-d');
$stmt = db()->prepare("SELECT c.name_en, c.name_ar, SUM(e.amount) as total
FROM expenses e
JOIN expense_categories c ON e.category_id = c.id
WHERE e.expense_date BETWEEN ? AND ?
GROUP BY c.id
ORDER BY total DESC");
$stmt->execute([$start_date, $end_date]);
$data['report_by_category'] = $stmt->fetchAll();
$stmt = db()->prepare("SELECT SUM(amount) FROM expenses WHERE expense_date BETWEEN ? AND ?");
$stmt->execute([$start_date, $end_date]);
$data['total_expenses'] = $stmt->fetchColumn() ?: 0;
break;
default:
$data['customers'] = db()->query("SELECT * FROM customers WHERE type = 'customer' ORDER BY id DESC LIMIT 5")->fetchAll();
// Dashboard stats
@ -1297,8 +1408,22 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
<a href="index.php?page=quotations" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'quotations' ? 'active' : '' ?>">
<i class="bi bi-file-earmark-text"></i> <span data-en="Quotations" data-ar="العروض">Quotations</span>
</a>
<a href="#" class="nav-link">
<i class="bi bi-wallet2"></i> <span data-en="Expenses" data-ar="المصروفات">Expenses</span>
</div>
<!-- Expenses Section -->
<div class="nav-section-title px-4 mt-3 mb-1 text-uppercase text-muted <?= !in_array($page, ['expense_categories', 'expenses', 'expense_report']) ? 'collapsed' : '' ?>" data-bs-toggle="collapse" data-bs-target="#expenses-collapse">
<span data-en="Expenses" data-ar="المصروفات">Expenses</span>
<i class="bi bi-chevron-down"></i>
</div>
<div class="collapse <?= in_array($page, ['expense_categories', 'expenses', 'expense_report']) ? 'show' : '' ?>" id="expenses-collapse">
<a href="index.php?page=expense_categories" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'expense_categories' ? 'active' : '' ?>">
<i class="bi bi-tags"></i> <span data-en="Categories" data-ar="الفئات">Categories</span>
</a>
<a href="index.php?page=expenses" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'expenses' ? 'active' : '' ?>">
<i class="bi bi-wallet2"></i> <span data-en="Expenses List" data-ar="قائمة المصروفات">Expenses List</span>
</a>
<a href="index.php?page=expense_report" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'expense_report' ? 'active' : '' ?>">
<i class="bi bi-file-earmark-bar-graph"></i> <span data-en="Expense Report" data-ar="تقرير المصروفات">Expense Report</span>
</a>
</div>
@ -3099,6 +3224,333 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
</div>
</div>
</div>
<?php elseif ($page === 'expense_categories'): ?>
<div class="card p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="m-0" data-en="Expense Categories" data-ar="فئات المصروفات">Expense Categories</h5>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addExpenseCategoryModal">
<i class="bi bi-plus-lg"></i> <span data-en="Add Category" data-ar="إضافة فئة">Add Category</span>
</button>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead>
<tr>
<th data-en="ID" data-ar="المعرف">ID</th>
<th data-en="Name (EN)" data-ar="الاسم (إنجليزي)">Name (EN)</th>
<th data-en="Name (AR)" data-ar="الاسم (عربي)">Name (AR)</th>
<th data-en="Actions" data-ar="الإجراءات" class="text-end">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($data['expense_categories'] as $cat): ?>
<tr>
<td><?= $cat['id'] ?></td>
<td><?= htmlspecialchars($cat['name_en']) ?></td>
<td><?= htmlspecialchars($cat['name_ar']) ?></td>
<td class="text-end">
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#editExpCatModal<?= $cat['id'] ?>"><i class="bi bi-pencil"></i></button>
<form method="POST" class="d-inline" onsubmit="return confirm('Are you sure?')">
<input type="hidden" name="id" value="<?= $cat['id'] ?>">
<button type="submit" name="delete_expense_category" class="btn btn-outline-danger"><i class="bi bi-trash"></i></button>
</form>
</div>
<!-- Edit Modal -->
<div class="modal fade" id="editExpCatModal<?= $cat['id'] ?>" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content text-start">
<div class="modal-header">
<h5 class="modal-title">Edit Category</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST">
<input type="hidden" name="id" value="<?= $cat['id'] ?>">
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Name (EN)</label>
<input type="text" name="name_en" class="form-control" value="<?= htmlspecialchars($cat['name_en']) ?>" required>
</div>
<div class="mb-3">
<label class="form-label">Name (AR)</label>
<input type="text" name="name_ar" class="form-control" value="<?= htmlspecialchars($cat['name_ar']) ?>" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancel</button>
<button type="submit" name="edit_expense_category" class="btn btn-primary">Update</button>
</div>
</form>
</div>
</div>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- Add Modal -->
<div class="modal fade" id="addExpenseCategoryModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Category</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST">
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Name (EN)</label>
<input type="text" name="name_en" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Name (AR)</label>
<input type="text" name="name_ar" class="form-control" required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancel</button>
<button type="submit" name="add_expense_category" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
<?php elseif ($page === 'expenses'): ?>
<div class="card p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="m-0" data-en="Expenses List" data-ar="قائمة المصروفات">Expenses List</h5>
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addExpenseModal">
<i class="bi bi-plus-lg"></i> <span data-en="Add Expense" data-ar="إضافة مصروف">Add Expense</span>
</button>
</div>
<div class="bg-light p-3 rounded mb-4">
<form method="GET" class="row g-3">
<input type="hidden" name="page" value="expenses">
<div class="col-md-3">
<label class="form-label small">Category</label>
<select name="category_id" class="form-select">
<option value="">All</option>
<?php foreach ($data['expense_categories'] as $c): ?>
<option value="<?= $c['id'] ?>" <?= ($_GET['category_id'] ?? '') == $c['id'] ? 'selected' : '' ?>><?= htmlspecialchars($c['name_en']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-3">
<label class="form-label small">Start Date</label>
<input type="date" name="start_date" class="form-control" value="<?= htmlspecialchars($_GET['start_date'] ?? '') ?>">
</div>
<div class="col-md-3">
<label class="form-label small">End Date</label>
<input type="date" name="end_date" class="form-control" value="<?= htmlspecialchars($_GET['end_date'] ?? '') ?>">
</div>
<div class="col-md-3 d-flex align-items-end">
<button type="submit" class="btn btn-primary w-100">Filter</button>
</div>
</form>
</div>
<div class="table-responsive">
<table class="table table-hover align-middle">
<thead>
<tr>
<th>Date</th>
<th>Reference</th>
<th>Category</th>
<th>Description</th>
<th class="text-end">Amount</th>
<th class="text-end">Actions</th>
</tr>
</thead>
<tbody>
<?php foreach ($data['expenses'] as $exp): ?>
<tr>
<td><?= $exp['expense_date'] ?></td>
<td><?= htmlspecialchars($exp['reference_no'] ?: '---') ?></td>
<td><?= htmlspecialchars($exp['cat_en'] ?? 'Unknown') ?></td>
<td><?= htmlspecialchars($exp['description']) ?></td>
<td class="text-end fw-bold">OMR <?= number_format((float)$exp['amount'], 3) ?></td>
<td class="text-end">
<div class="btn-group btn-group-sm">
<button class="btn btn-outline-primary" data-bs-toggle="modal" data-bs-target="#editExpenseModal<?= $exp['id'] ?>"><i class="bi bi-pencil"></i></button>
<form method="POST" class="d-inline" onsubmit="return confirm('Are you sure?')">
<input type="hidden" name="id" value="<?= $exp['id'] ?>">
<button type="submit" name="delete_expense" class="btn btn-outline-danger"><i class="bi bi-trash"></i></button>
</form>
</div>
<!-- Edit Modal -->
<div class="modal fade" id="editExpenseModal<?= $exp['id'] ?>" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content text-start">
<div class="modal-header">
<h5 class="modal-title">Edit Expense</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST">
<input type="hidden" name="id" value="<?= $exp['id'] ?>">
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Category</label>
<select name="category_id" class="form-select" required>
<?php foreach ($data['expense_categories'] as $c): ?>
<option value="<?= $c['id'] ?>" <?= $c['id'] == $exp['category_id'] ? 'selected' : '' ?>><?= htmlspecialchars($c['name_en']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Date</label>
<input type="date" name="expense_date" class="form-control" value="<?= $exp['expense_date'] ?>" required>
</div>
<div class="mb-3">
<label class="form-label">Amount</label>
<input type="number" step="0.001" name="amount" class="form-control" value="<?= (float)$exp['amount'] ?>" required>
</div>
<div class="mb-3">
<label class="form-label">Reference No</label>
<input type="text" name="reference_no" class="form-control" value="<?= htmlspecialchars($exp['reference_no']) ?>">
</div>
<div class="mb-3">
<label class="form-label">Description</label>
<textarea name="description" class="form-control"><?= htmlspecialchars($exp['description']) ?></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancel</button>
<button type="submit" name="edit_expense" class="btn btn-primary">Update</button>
</div>
</form>
</div>
</div>
</div>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
<!-- Add Expense Modal -->
<div class="modal fade" id="addExpenseModal" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title">Add Expense</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
</div>
<form method="POST">
<div class="modal-body">
<div class="mb-3">
<label class="form-label">Category</label>
<select name="category_id" class="form-select" required>
<option value="">Select Category</option>
<?php foreach ($data['expense_categories'] as $c): ?>
<option value="<?= $c['id'] ?>"><?= htmlspecialchars($c['name_en']) ?></option>
<?php endforeach; ?>
</select>
</div>
<div class="mb-3">
<label class="form-label">Date</label>
<input type="date" name="expense_date" class="form-control" value="<?= date('Y-m-d') ?>" required>
</div>
<div class="mb-3">
<label class="form-label">Amount</label>
<input type="number" step="0.001" name="amount" class="form-control" required>
</div>
<div class="mb-3">
<label class="form-label">Reference No</label>
<input type="text" name="reference_no" class="form-control">
</div>
<div class="mb-3">
<label class="form-label">Description</label>
<textarea name="description" class="form-control"></textarea>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-light" data-bs-dismiss="modal">Cancel</button>
<button type="submit" name="add_expense" class="btn btn-primary">Save</button>
</div>
</form>
</div>
</div>
</div>
<?php elseif ($page === 'expense_report'): ?>
<div class="card p-4">
<div class="d-flex justify-content-between align-items-center mb-4">
<h5 class="m-0" data-en="Expense Report" data-ar="تقرير المصروفات">Expense Report</h5>
<button class="btn btn-outline-secondary d-print-none" onclick="window.print()">
<i class="bi bi-printer"></i> Print
</button>
</div>
<div class="bg-light p-3 rounded mb-4 d-print-none">
<form method="GET" class="row g-3">
<input type="hidden" name="page" value="expense_report">
<div class="col-md-4">
<label class="form-label small">From Date</label>
<input type="date" name="start_date" class="form-control" value="<?= htmlspecialchars($_GET['start_date'] ?? date('Y-m-01')) ?>">
</div>
<div class="col-md-4">
<label class="form-label small">To Date</label>
<input type="date" name="end_date" class="form-control" value="<?= htmlspecialchars($_GET['end_date'] ?? date('Y-m-d')) ?>">
</div>
<div class="col-md-4 d-flex align-items-end">
<button type="submit" class="btn btn-primary w-100">Generate Report</button>
</div>
</form>
</div>
<div class="row mb-4">
<div class="col-md-12">
<div class="card bg-light border-0">
<div class="card-body text-center">
<h6 class="text-muted text-uppercase mb-2">Total Expenses</h6>
<h2 class="text-danger mb-0">OMR <?= number_format((float)$data['total_expenses'], 3) ?></h2>
<small class="text-muted">Period: <?= htmlspecialchars($_GET['start_date'] ?? date('Y-m-01')) ?> to <?= htmlspecialchars($_GET['end_date'] ?? date('Y-m-d')) ?></small>
</div>
</div>
</div>
</div>
<div class="table-responsive">
<table class="table table-bordered">
<thead class="bg-light">
<tr>
<th>Category</th>
<th class="text-end">Total Amount</th>
<th class="text-end">% of Total</th>
</tr>
</thead>
<tbody>
<?php if (empty($data['report_by_category'])): ?>
<tr><td colspan="3" class="text-center text-muted">No expenses found for this period.</td></tr>
<?php else: ?>
<?php foreach ($data['report_by_category'] as $row):
$percent = $data['total_expenses'] > 0 ? ($row['total'] / $data['total_expenses'] * 100) : 0;
?>
<tr>
<td>
<div><?= htmlspecialchars($row['name_en']) ?></div>
<small class="text-muted"><?= htmlspecialchars($row['name_ar']) ?></small>
</td>
<td class="text-end fw-bold">OMR <?= number_format((float)$row['total'], 3) ?></td>
<td class="text-end"><?= number_format($percent, 1) ?>%</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
<?php endif; ?>
</div>