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'; + + +
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ + + Export + + + + + + +
+
+
@@ -1003,6 +1148,30 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; + + +
+
+ +
+ + +
+
+ + + Export + + + + + + +
+ +
@@ -1203,6 +1372,45 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; Create New Invoice + + +
+
+ +
+ + +
+
+ + +
+
+ + +
+
+ + +
+
+ + + Export + + + Clear + +
+ +
@@ -1305,6 +1513,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; + @@ -1314,17 +1523,17 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; - + - + - + @@ -1391,6 +1600,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; + @@ -1400,17 +1610,17 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; - + - + - + @@ -1481,6 +1691,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; + @@ -1489,15 +1700,15 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System'; - + - + - + @@ -2223,10 +2434,10 @@ document.addEventListener('DOMContentLoaded', function() {
${item.name_en}
${item.name_ar} (${item.sku})
-
VAT: ${vatRate}%
+ `; @@ -2335,6 +2546,7 @@ document.addEventListener('DOMContentLoaded', function() { + `; 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
Item Quantity Unit PriceVAT % Total
SubtotalSubtotal $0.00
VAT AmountVAT Amount $0.00
Grand Total (Inc. VAT)Grand Total (Inc. VAT) $0.00
Item Quantity Unit PriceVAT % Total
SubtotalSubtotal $0.00
VAT AmountVAT Amount $0.00
Grand Total (Inc. VAT)Grand Total (Inc. VAT) $0.00
Description Qty PriceVAT % Total
SubtotalSubtotal
VAT AmountVAT Amount
Total (Inc. VAT)Total (Inc. VAT)
${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)}