diff --git a/index.php b/index.php index 3c5aa11..518217d 100644 --- a/index.php +++ b/index.php @@ -537,6 +537,60 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $page = $_GET['page'] ?? 'dashboard'; $data = []; +if ($page === 'export') { + $type = $_GET['type'] ?? 'sales'; + $filename = $type . "_export_" . date('Y-m-d') . ".csv"; + + header('Content-Type: text/csv; charset=utf-8'); + header('Content-Disposition: attachment; filename=' . $filename); + $output = fopen('php://output', 'w'); + + // Add UTF-8 BOM for Excel + fprintf($output, chr(0xEF).chr(0xBB).chr(0xBF)); + + if ($type === 'sales' || $type === 'purchases') { + $invType = ($type === 'sales') ? 'sale' : 'purchase'; + $where = ["v.type = ?"]; + $params = [$invType]; + if (!empty($_GET['search'])) { $where[] = "(v.id LIKE ? OR c.name LIKE ?)"; $params[] = "%{$_GET['search']}%"; $params[] = "%{$_GET['search']}%"; } + if (!empty($_GET['customer_id'])) { $where[] = "v.customer_id = ?"; $params[] = $_GET['customer_id']; } + if (!empty($_GET['start_date'])) { $where[] = "v.invoice_date >= ?"; $params[] = $_GET['start_date']; } + if (!empty($_GET['end_date'])) { $where[] = "v.invoice_date <= ?"; $params[] = $_GET['end_date']; } + $whereSql = implode(" AND ", $where); + $stmt = db()->prepare("SELECT v.id, c.name as customer_name, v.invoice_date, v.payment_type, v.total_amount, v.vat_amount, v.total_with_vat + FROM invoices v LEFT JOIN customers c ON v.customer_id = c.id + WHERE $whereSql ORDER BY v.id DESC"); + $stmt->execute($params); + fputcsv($output, ['Invoice ID', 'Customer/Supplier', 'Date', 'Payment', 'Subtotal', 'VAT', 'Total']); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) fputcsv($output, $row); + } elseif ($type === 'customers' || $type === 'suppliers') { + $custType = ($type === 'suppliers') ? 'supplier' : 'customer'; + $where = ["type = ?"]; + $params = [$custType]; + if (!empty($_GET['search'])) { $where[] = "(name LIKE ? OR email LIKE ? OR phone LIKE ?)"; $params[] = "%{$_GET['search']}%"; $params[] = "%{$_GET['search']}%"; $params[] = "%{$_GET['search']}%"; } + if (!empty($_GET['start_date'])) { $where[] = "DATE(created_at) >= ?"; $params[] = $_GET['start_date']; } + if (!empty($_GET['end_date'])) { $where[] = "DATE(created_at) <= ?"; $params[] = $_GET['end_date']; } + $whereSql = implode(" AND ", $where); + $stmt = db()->prepare("SELECT id, name, email, phone, balance, created_at FROM customers WHERE $whereSql ORDER BY id DESC"); + $stmt->execute($params); + fputcsv($output, ['ID', 'Name', 'Email', 'Phone', 'Balance', 'Created At']); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) fputcsv($output, $row); + } elseif ($type === 'items') { + $where = ["1=1"]; + $params = []; + if (!empty($_GET['search'])) { $where[] = "(i.name_en LIKE ? OR i.name_ar LIKE ? OR i.sku LIKE ?)"; $params[] = "%{$_GET['search']}%"; $params[] = "%{$_GET['search']}%"; $params[] = "%{$_GET['search']}%"; } + $whereSql = implode(" AND ", $where); + $stmt = db()->prepare("SELECT i.sku, i.name_en, i.name_ar, c.name_en as category, i.purchase_price, i.sale_price, i.stock_quantity, i.vat_rate + FROM stock_items i LEFT JOIN stock_categories c ON i.category_id = c.id + WHERE $whereSql ORDER BY i.id DESC"); + $stmt->execute($params); + fputcsv($output, ['SKU', 'Name (EN)', 'Name (AR)', 'Category', 'Purchase Price', 'Sale Price', 'Quantity', 'VAT %']); + while ($row = $stmt->fetch(PDO::FETCH_ASSOC)) fputcsv($output, $row); + } + fclose($output); + exit; +} + // Global data for modals $data['categories'] = db()->query("SELECT * FROM stock_categories ORDER BY name_en ASC")->fetchAll(); $data['units'] = db()->query("SELECT * FROM stock_units ORDER BY name_en ASC")->fetchAll(); @@ -550,10 +604,28 @@ foreach ($settings_raw as $s) { switch ($page) { case 'suppliers': - $data['customers'] = db()->query("SELECT * FROM customers WHERE type = 'supplier' ORDER BY id DESC")->fetchAll(); - break; case 'customers': - $data['customers'] = db()->query("SELECT * FROM customers WHERE type = 'customer' ORDER BY id DESC")->fetchAll(); + $type = ($page === 'suppliers') ? 'supplier' : 'customer'; + $where = ["type = ?"]; + $params = [$type]; + if (!empty($_GET['search'])) { + $where[] = "(name LIKE ? OR email LIKE ? OR phone LIKE ?)"; + $params[] = "%{$_GET['search']}%"; + $params[] = "%{$_GET['search']}%"; + $params[] = "%{$_GET['search']}%"; + } + if (!empty($_GET['start_date'])) { + $where[] = "DATE(created_at) >= ?"; + $params[] = $_GET['start_date']; + } + if (!empty($_GET['end_date'])) { + $where[] = "DATE(created_at) <= ?"; + $params[] = $_GET['end_date']; + } + $whereSql = implode(" AND ", $where); + $stmt = db()->prepare("SELECT * FROM customers WHERE $whereSql ORDER BY id DESC"); + $stmt->execute($params); + $data['customers'] = $stmt->fetchAll(); break; case 'categories': // Already fetched globally @@ -562,12 +634,24 @@ switch ($page) { // Already fetched globally break; case 'items': - $data['items'] = db()->query("SELECT i.*, c.name_en as cat_en, c.name_ar as cat_ar, u.short_name_en as unit_en, u.short_name_ar as unit_ar, s.name as supplier_name + $where = ["1=1"]; + $params = []; + if (!empty($_GET['search'])) { + $where[] = "(i.name_en LIKE ? OR i.name_ar LIKE ? OR i.sku LIKE ?)"; + $params[] = "%{$_GET['search']}%"; + $params[] = "%{$_GET['search']}%"; + $params[] = "%{$_GET['search']}%"; + } + $whereSql = implode(" AND ", $where); + $stmt = db()->prepare("SELECT i.*, c.name_en as cat_en, c.name_ar as cat_ar, u.short_name_en as unit_en, u.short_name_ar as unit_ar, s.name as supplier_name FROM stock_items i LEFT JOIN stock_categories c ON i.category_id = c.id LEFT JOIN stock_units u ON i.unit_id = u.id LEFT JOIN customers s ON i.supplier_id = s.id - ORDER BY i.id DESC")->fetchAll(); + WHERE $whereSql + ORDER BY i.id DESC"); + $stmt->execute($params); + $data['items'] = $stmt->fetchAll(); break; case 'payment_methods': $data['payment_methods'] = db()->query("SELECT * FROM payment_methods ORDER BY id DESC")->fetchAll(); @@ -578,11 +662,40 @@ switch ($page) { case 'sales': case 'purchases': $type = ($page === 'sales') ? 'sale' : 'purchase'; - $data['invoices'] = db()->query("SELECT v.*, c.name as customer_name - FROM invoices v - LEFT JOIN customers c ON v.customer_id = c.id - WHERE v.type = '$type' - ORDER BY v.id DESC")->fetchAll(); + + $where = ["v.type = ?"]; + $params = [$type]; + + if (!empty($_GET['search'])) { + $where[] = "(v.id LIKE ? OR c.name LIKE ?)"; + $params[] = "%{$_GET['search']}%"; + $params[] = "%{$_GET['search']}%"; + } + + if (!empty($_GET['customer_id'])) { + $where[] = "v.customer_id = ?"; + $params[] = $_GET['customer_id']; + } + + if (!empty($_GET['start_date'])) { + $where[] = "v.invoice_date >= ?"; + $params[] = $_GET['start_date']; + } + + if (!empty($_GET['end_date'])) { + $where[] = "v.invoice_date <= ?"; + $params[] = $_GET['end_date']; + } + + $whereSql = implode(" AND ", $where); + $stmt = db()->prepare("SELECT v.*, c.name as customer_name + FROM invoices v + LEFT JOIN customers c ON v.customer_id = c.id + WHERE $whereSql + ORDER BY v.id DESC"); + $stmt->execute($params); + $data['invoices'] = $stmt->fetchAll(); + $data['items_list'] = db()->query("SELECT id, name_en, name_ar, sale_price, purchase_price, stock_quantity, vat_rate FROM stock_items ORDER BY name_en ASC")->fetchAll(); $data['customers_list'] = db()->query("SELECT id, name FROM customers WHERE type = '" . ($type === 'sale' ? 'customer' : 'supplier') . "' ORDER BY name ASC")->fetchAll(); break; @@ -845,6 +958,38 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; + + +
| Item | Quantity | Unit Price | +VAT % | Total | @@ -1314,17 +1523,17 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; | |||
|---|---|---|---|---|---|---|---|---|
| Subtotal | +Subtotal | $0.00 | ||||||
| VAT Amount | +VAT Amount | $0.00 | ||||||
| Grand Total (Inc. VAT) | +Grand Total (Inc. VAT) | $0.00 | Item | Quantity | Unit Price | +VAT % | Total | @@ -1400,17 +1610,17 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; |
| Subtotal | +Subtotal | $0.00 | ||||||
| VAT Amount | +VAT Amount | $0.00 | ||||||
| Grand Total (Inc. VAT) | +Grand Total (Inc. VAT) | $0.00 | Description | Qty | Price | +VAT % | Total | @@ -1489,15 +1700,15 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';|
| Subtotal | +Subtotal | |||||||
| VAT Amount | +VAT Amount | |||||||
| Total (Inc. VAT) | +Total (Inc. VAT) | + | `; @@ -2335,6 +2546,7 @@ document.addEventListener('DOMContentLoaded', function() { | ${item.name_en} / ${item.name_ar} | ${item.quantity} | $${parseFloat(item.unit_price).toFixed(2)} | +${parseFloat(item.vat_rate || 0).toFixed(2)}% | $${parseFloat(item.total_price).toFixed(2)} | `; body.appendChild(tr); diff --git a/uploads/favicon.pdf b/uploads/favicon.pdf new file mode 100644 index 0000000..a008614 Binary files /dev/null and b/uploads/favicon.pdf differ diff --git a/uploads/favicon.png b/uploads/favicon.png new file mode 100644 index 0000000..2ae8817 Binary files /dev/null and b/uploads/favicon.png differ