Autosave: 20260216-091806
This commit is contained in:
parent
de6c7ed61b
commit
4b20014812
20
db/migrations/20260216_add_invoices.sql
Normal file
20
db/migrations/20260216_add_invoices.sql
Normal file
@ -0,0 +1,20 @@
|
||||
CREATE TABLE IF NOT EXISTS invoices (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
customer_id INT,
|
||||
invoice_date DATE NOT NULL,
|
||||
type ENUM('sale', 'purchase') NOT NULL,
|
||||
total_amount DECIMAL(15, 2) DEFAULT 0.00,
|
||||
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
||||
FOREIGN KEY (customer_id) REFERENCES customers(id) ON DELETE SET NULL
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS invoice_items (
|
||||
id INT AUTO_INCREMENT PRIMARY KEY,
|
||||
invoice_id INT NOT NULL,
|
||||
item_id INT NOT NULL,
|
||||
quantity DECIMAL(15, 2) NOT NULL,
|
||||
unit_price DECIMAL(15, 2) NOT NULL,
|
||||
total_price DECIMAL(15, 2) NOT NULL,
|
||||
FOREIGN KEY (invoice_id) REFERENCES invoices(id) ON DELETE CASCADE,
|
||||
FOREIGN KEY (item_id) REFERENCES stock_items(id) ON DELETE CASCADE
|
||||
);
|
||||
1
db/migrations/20260216_update_invoices_payment.sql
Normal file
1
db/migrations/20260216_update_invoices_payment.sql
Normal file
@ -0,0 +1 @@
|
||||
ALTER TABLE invoices ADD COLUMN payment_type ENUM('cash', 'credit') DEFAULT 'cash' AFTER type;
|
||||
698
index.php
698
index.php
@ -4,6 +4,15 @@ require_once 'db/config.php';
|
||||
|
||||
// Handle POST Requests
|
||||
$message = '';
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'GET' && isset($_GET['action']) && $_GET['action'] === 'search_items') {
|
||||
header('Content-Type: application/json');
|
||||
$q = $_GET['q'] ?? '';
|
||||
$stmt = db()->prepare("SELECT id, name_en, name_ar, sku, sale_price, purchase_price, stock_quantity FROM stock_items WHERE name_en LIKE ? OR name_ar LIKE ? OR sku LIKE ? LIMIT 10");
|
||||
$stmt->execute(["%$q%", "%$q%", "%$q%"]);
|
||||
echo json_encode($stmt->fetchAll());
|
||||
exit;
|
||||
}
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
if (isset($_POST['add_customer'])) {
|
||||
$name = $_POST['name'] ?? '';
|
||||
@ -186,6 +195,122 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['import_customers']) || isset($_POST['import_suppliers'])) {
|
||||
$type = isset($_POST['import_customers']) ? 'customer' : 'supplier';
|
||||
if (isset($_FILES['excel_file']) && $_FILES['excel_file']['error'] === UPLOAD_ERR_OK) {
|
||||
$file = $_FILES['excel_file']['tmp_name'];
|
||||
$handle = fopen($file, 'r');
|
||||
$header = fgetcsv($handle);
|
||||
$count = 0;
|
||||
while (($row = fgetcsv($handle)) !== FALSE) {
|
||||
if (count($row) < 4) continue;
|
||||
$name = trim($row[0]);
|
||||
$email = trim($row[1]);
|
||||
$phone = trim($row[2]);
|
||||
$balance = (float)trim($row[3]);
|
||||
if ($name) {
|
||||
$stmt = db()->prepare("INSERT INTO customers (name, email, phone, balance, type) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$name, $email, $phone, $balance, $type]);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
$message = "$count " . ($type === 'customer' ? 'customers' : 'suppliers') . " imported successfully!";
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['import_categories'])) {
|
||||
if (isset($_FILES['excel_file']) && $_FILES['excel_file']['error'] === UPLOAD_ERR_OK) {
|
||||
$file = $_FILES['excel_file']['tmp_name'];
|
||||
$handle = fopen($file, 'r');
|
||||
$header = fgetcsv($handle);
|
||||
$count = 0;
|
||||
while (($row = fgetcsv($handle)) !== FALSE) {
|
||||
if (count($row) < 2) continue;
|
||||
$name_en = trim($row[0]);
|
||||
$name_ar = trim($row[1]);
|
||||
if ($name_en && $name_ar) {
|
||||
$stmt = db()->prepare("INSERT INTO stock_categories (name_en, name_ar) VALUES (?, ?)");
|
||||
$stmt->execute([$name_en, $name_ar]);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
$message = "$count categories imported successfully!";
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['import_units'])) {
|
||||
if (isset($_FILES['excel_file']) && $_FILES['excel_file']['error'] === UPLOAD_ERR_OK) {
|
||||
$file = $_FILES['excel_file']['tmp_name'];
|
||||
$handle = fopen($file, 'r');
|
||||
$header = fgetcsv($handle);
|
||||
$count = 0;
|
||||
while (($row = fgetcsv($handle)) !== FALSE) {
|
||||
if (count($row) < 4) continue;
|
||||
$name_en = trim($row[0]);
|
||||
$name_ar = trim($row[1]);
|
||||
$short_en = trim($row[2]);
|
||||
$short_ar = trim($row[3]);
|
||||
if ($name_en && $name_ar) {
|
||||
$stmt = db()->prepare("INSERT INTO stock_units (name_en, name_ar, short_name_en, short_name_ar) VALUES (?, ?, ?, ?)");
|
||||
$stmt->execute([$name_en, $name_ar, $short_en, $short_ar]);
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
fclose($handle);
|
||||
$message = "$count units imported successfully!";
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['add_invoice'])) {
|
||||
$customer_id = $_POST['customer_id'] ?: null;
|
||||
$invoice_date = $_POST['invoice_date'] ?: date('Y-m-d');
|
||||
$type = $_POST['type'] ?? 'sale'; // 'sale' or 'purchase'
|
||||
$payment_type = $_POST['payment_type'] ?? 'cash';
|
||||
$item_ids = $_POST['item_ids'] ?? [];
|
||||
$quantities = $_POST['quantities'] ?? [];
|
||||
$prices = $_POST['prices'] ?? [];
|
||||
|
||||
if (!empty($item_ids)) {
|
||||
$db = db();
|
||||
$db->beginTransaction();
|
||||
try {
|
||||
$total_amount = 0;
|
||||
foreach ($item_ids as $index => $item_id) {
|
||||
$total_amount += (float)$quantities[$index] * (float)$prices[$index];
|
||||
}
|
||||
|
||||
$stmt = $db->prepare("INSERT INTO invoices (customer_id, invoice_date, type, payment_type, total_amount) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$customer_id, $invoice_date, $type, $payment_type, $total_amount]);
|
||||
$invoice_id = $db->lastInsertId();
|
||||
|
||||
foreach ($item_ids as $index => $item_id) {
|
||||
$qty = (float)$quantities[$index];
|
||||
$price = (float)$prices[$index];
|
||||
$total_price = $qty * $price;
|
||||
|
||||
$stmt = $db->prepare("INSERT INTO invoice_items (invoice_id, item_id, quantity, unit_price, total_price) VALUES (?, ?, ?, ?, ?)");
|
||||
$stmt->execute([$invoice_id, $item_id, $qty, $price, $total_price]);
|
||||
|
||||
// Update stock level
|
||||
if ($type === 'sale') {
|
||||
$stmt = $db->prepare("UPDATE stock_items SET stock_quantity = stock_quantity - ? WHERE id = ?");
|
||||
} else {
|
||||
$stmt = $db->prepare("UPDATE stock_items SET stock_quantity = stock_quantity + ? WHERE id = ?");
|
||||
}
|
||||
$stmt->execute([$qty, $item_id]);
|
||||
}
|
||||
|
||||
$db->commit();
|
||||
$message = ucfirst($type) . " invoice created successfully!";
|
||||
} catch (Exception $e) {
|
||||
$db->rollBack();
|
||||
$message = "Error creating invoice: " . $e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isset($_POST['add_payment_method'])) {
|
||||
$name_en = $_POST['name_en'] ?? '';
|
||||
$name_ar = $_POST['name_ar'] ?? '';
|
||||
@ -250,6 +375,17 @@ switch ($page) {
|
||||
case 'payment_methods':
|
||||
$data['payment_methods'] = db()->query("SELECT * FROM payment_methods ORDER BY id DESC")->fetchAll();
|
||||
break;
|
||||
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();
|
||||
$data['items_list'] = db()->query("SELECT id, name_en, name_ar, sale_price, purchase_price, stock_quantity 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;
|
||||
default:
|
||||
$data['customers'] = db()->query("SELECT * FROM customers WHERE type = 'customer' ORDER BY id DESC LIMIT 5")->fetchAll();
|
||||
// Dashboard stats
|
||||
@ -273,44 +409,91 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
|
||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?= time() ?>">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<style>
|
||||
@media print {
|
||||
.sidebar, .topbar, .d-print-none, .btn, .modal-header, .modal-footer {
|
||||
display: none !important;
|
||||
}
|
||||
.main-content {
|
||||
margin-left: 0 !important;
|
||||
padding: 0 !important;
|
||||
}
|
||||
.modal {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 0;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
visibility: visible;
|
||||
overflow: visible !important;
|
||||
display: block !important;
|
||||
}
|
||||
.modal-dialog {
|
||||
max-width: 100% !important;
|
||||
width: 100% !important;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
.modal-content {
|
||||
border: none !important;
|
||||
box-shadow: none !important;
|
||||
}
|
||||
body {
|
||||
background: white !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="sidebar">
|
||||
<div class="sidebar-header" data-en="Accounting" data-ar="المحاسبة">Accounting</div>
|
||||
<nav class="mt-4">
|
||||
<!-- General Section -->
|
||||
<a href="index.php?page=dashboard" class="nav-link <?= !isset($_GET['page']) || $_GET['page'] === 'dashboard' ? 'active' : '' ?>">
|
||||
<i class="bi bi-speedometer2"></i> <span data-en="Dashboard" data-ar="لوحة القيادة">Dashboard</span>
|
||||
</a>
|
||||
<a href="index.php?page=customers" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'customers' ? 'active' : '' ?>">
|
||||
<i class="bi bi-people"></i> <span data-en="Customers" data-ar="العملاء">Customers</span>
|
||||
|
||||
<!-- Operations Section -->
|
||||
<div class="nav-section-title px-4 mt-3 mb-1 text-uppercase small text-muted" data-en="Operations" data-ar="العمليات">Operations</div>
|
||||
<a href="index.php?page=sales" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'sales' ? 'active' : '' ?>">
|
||||
<i class="bi bi-cart"></i> <span data-en="Sales Invoices" data-ar="فواتير المبيعات">Sales Invoices</span>
|
||||
</a>
|
||||
<a href="index.php?page=purchases" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'purchases' ? 'active' : '' ?>">
|
||||
<i class="bi bi-bag"></i> <span data-en="Purchase Invoices" data-ar="فواتير المشتريات">Purchase Invoices</span>
|
||||
</a>
|
||||
<a href="#" class="nav-link">
|
||||
<i class="bi bi-wallet2"></i> <span data-en="Expenses" data-ar="المصروفات">Expenses</span>
|
||||
</a>
|
||||
|
||||
<!-- Inventory Section -->
|
||||
<div class="nav-section-title px-4 mt-3 mb-1 text-uppercase small text-muted" data-en="Inventory" data-ar="المخزون">Inventory</div>
|
||||
<a href="index.php?page=items" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'items' ? 'active' : '' ?>">
|
||||
<i class="bi bi-box-seam"></i> <span data-en="Items" data-ar="الأصناف">Items</span>
|
||||
</a>
|
||||
|
||||
<div class="nav-section-title px-4 mt-3 mb-1 text-uppercase small text-muted" data-en="Stock Management" data-ar="إدارة المخزون">Stock Management</div>
|
||||
<a href="index.php?page=categories" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'categories' ? 'active' : '' ?>">
|
||||
<i class="bi bi-tags"></i> <span data-en="Categories" data-ar="الفئات">Categories</span>
|
||||
</a>
|
||||
<a href="index.php?page=units" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'units' ? 'active' : '' ?>">
|
||||
<i class="bi bi-calculator"></i> <span data-en="Units" data-ar="الوحدات">Units</span>
|
||||
</a>
|
||||
<a href="index.php?page=items" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'items' ? 'active' : '' ?>">
|
||||
<i class="bi bi-box-seam"></i> <span data-en="Items" data-ar="الأصناف">Items</span>
|
||||
</a>
|
||||
|
||||
<div class="nav-section-title px-4 mt-3 mb-1 text-uppercase small text-muted" data-en="Other" data-ar="أخرى">Other</div>
|
||||
<!-- People Section -->
|
||||
<div class="nav-section-title px-4 mt-3 mb-1 text-uppercase small text-muted" data-en="Relationships" data-ar="العلاقات">Relationships</div>
|
||||
<a href="index.php?page=customers" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'customers' ? 'active' : '' ?>">
|
||||
<i class="bi bi-people"></i> <span data-en="Customers" data-ar="العملاء">Customers</span>
|
||||
</a>
|
||||
<a href="index.php?page=suppliers" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'suppliers' ? 'active' : '' ?>">
|
||||
<i class="bi bi-truck"></i> <span data-en="Suppliers" data-ar="الموردون">Suppliers</span>
|
||||
</a>
|
||||
|
||||
<!-- Configuration Section -->
|
||||
<div class="nav-section-title px-4 mt-3 mb-1 text-uppercase small text-muted" data-en="Configuration" data-ar="الإعدادات">Configuration</div>
|
||||
<a href="index.php?page=payment_methods" class="nav-link <?= isset($_GET['page']) && $_GET['page'] === 'payment_methods' ? 'active' : '' ?>">
|
||||
<i class="bi bi-credit-card"></i> <span data-en="Payment Methods" data-ar="طرق الدفع">Payment Methods</span>
|
||||
</a>
|
||||
<a href="#" class="nav-link">
|
||||
<i class="bi bi-cart"></i> <span data-en="Sales" data-ar="المبيعات">Sales</span>
|
||||
</a>
|
||||
<a href="#" class="nav-link">
|
||||
<i class="bi bi-wallet2"></i> <span data-en="Expenses" data-ar="المصروفات">Expenses</span>
|
||||
</a>
|
||||
<a href="#" class="nav-link">
|
||||
<i class="bi bi-person-badge"></i> <span data-en="HR" data-ar="الموارد البشرية">HR</span>
|
||||
</a>
|
||||
@ -329,6 +512,8 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
'units' => ['en' => 'Stock Units', 'ar' => 'وحدات المخزون'],
|
||||
'items' => ['en' => 'Stock Items', 'ar' => 'أصناف المخزون'],
|
||||
'payment_methods' => ['en' => 'Payment Methods', 'ar' => 'طرق الدفع'],
|
||||
'sales' => ['en' => 'Sales Invoices', 'ar' => 'فواتير المبيعات'],
|
||||
'purchases' => ['en' => 'Purchase Invoices', 'ar' => 'فواتير المشتريات'],
|
||||
];
|
||||
$currTitle = $titles[$page] ?? $titles['dashboard'];
|
||||
?>
|
||||
@ -430,9 +615,12 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<button class="list-group-item list-group-item-action border-0 px-0" data-bs-toggle="modal" data-bs-target="#importItemsModal">
|
||||
<i class="bi bi-file-earmark-excel text-success"></i> <span data-en="Import Items" data-ar="استيراد أصناف">Import Items</span>
|
||||
</button>
|
||||
<button class="list-group-item list-group-item-action border-0 px-0">
|
||||
<i class="bi bi-receipt text-warning"></i> <span data-en="Create Invoice" data-ar="إنشاء فاتورة">Create Invoice</span>
|
||||
</button>
|
||||
<a href="index.php?page=sales" class="list-group-item list-group-item-action border-0 px-0">
|
||||
<i class="bi bi-cart text-primary"></i> <span data-en="Sales Invoices" data-ar="فواتير المبيعات">Sales Invoices</span>
|
||||
</a>
|
||||
<a href="index.php?page=purchases" class="list-group-item list-group-item-action border-0 px-0">
|
||||
<i class="bi bi-bag text-warning"></i> <span data-en="Purchase Invoices" data-ar="فواتير المشتريات">Purchase Invoices</span>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -441,9 +629,14 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<div class="card p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h5 class="m-0" data-en="<?= $currTitle['en'] ?> Management" data-ar="إدارة <?= $currTitle['ar'] ?>"><?= $currTitle['en'] ?> Management</h5>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addCustomerModal">
|
||||
<i class="bi bi-plus-lg"></i> <span data-en="Add <?= $currTitle['en'] ?>" data-ar="إضافة <?= $currTitle['ar'] ?>">Add <?= $currTitle['en'] ?></span>
|
||||
</button>
|
||||
<div>
|
||||
<button class="btn btn-outline-success me-2" data-bs-toggle="modal" data-bs-target="<?= $page === 'suppliers' ? '#importSuppliersModal' : '#importCustomersModal' ?>">
|
||||
<i class="bi bi-file-earmark-excel"></i> <span data-en="Import Excel" data-ar="استيراد من اكسل">Import Excel</span>
|
||||
</button>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addCustomerModal">
|
||||
<i class="bi bi-plus-lg"></i> <span data-en="Add <?= $currTitle['en'] ?>" data-ar="إضافة <?= $currTitle['ar'] ?>">Add <?= $currTitle['en'] ?></span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
@ -522,9 +715,14 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<div class="card p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h5 class="m-0" data-en="Stock Categories" data-ar="فئات المخزون">Stock Categories</h5>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addCategoryModal">
|
||||
<i class="bi bi-plus-lg"></i> <span data-en="Add Category" data-ar="إضافة فئة">Add Category</span>
|
||||
</button>
|
||||
<div>
|
||||
<button class="btn btn-outline-success me-2" data-bs-toggle="modal" data-bs-target="#importCategoriesModal">
|
||||
<i class="bi bi-file-earmark-excel"></i> <span data-en="Import Excel" data-ar="استيراد من اكسل">Import Excel</span>
|
||||
</button>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addCategoryModal">
|
||||
<i class="bi bi-plus-lg"></i> <span data-en="Add Category" data-ar="إضافة فئة">Add Category</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
@ -552,9 +750,14 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
<div class="card p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h5 class="m-0" data-en="Stock Units" data-ar="وحدات المخزون">Stock Units</h5>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addUnitModal">
|
||||
<i class="bi bi-plus-lg"></i> <span data-en="Add Unit" data-ar="إضافة وحدة">Add Unit</span>
|
||||
</button>
|
||||
<div>
|
||||
<button class="btn btn-outline-success me-2" data-bs-toggle="modal" data-bs-target="#importUnitsModal">
|
||||
<i class="bi bi-file-earmark-excel"></i> <span data-en="Import Excel" data-ar="استيراد من اكسل">Import Excel</span>
|
||||
</button>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addUnitModal">
|
||||
<i class="bi bi-plus-lg"></i> <span data-en="Add Unit" data-ar="إضافة وحدة">Add Unit</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
@ -778,6 +981,194 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<?php elseif ($page === 'sales' || $page === 'purchases'): ?>
|
||||
<div class="card p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
<h5 class="m-0" data-en="<?= $currTitle['en'] ?>" data-ar="<?= $currTitle['ar'] ?>"><?= $currTitle['en'] ?></h5>
|
||||
<button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#addInvoiceModal">
|
||||
<i class="bi bi-plus-lg"></i> <span data-en="Create New Invoice" data-ar="إنشاء فاتورة جديدة">Create New Invoice</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-hover align-middle">
|
||||
<thead>
|
||||
<tr>
|
||||
<th data-en="Invoice #" data-ar="رقم الفاتورة">Invoice #</th>
|
||||
<th data-en="Date" data-ar="التاريخ">Date</th>
|
||||
<th data-en="<?= $page === 'sales' ? 'Customer' : 'Supplier' ?>" data-ar="<?= $page === 'sales' ? 'العميل' : 'المورد' ?>"><?= $page === 'sales' ? 'Customer' : 'Supplier' ?></th>
|
||||
<th data-en="Total Amount" data-ar="إجمالي المبلغ" class="text-end">Total Amount</th>
|
||||
<th data-en="Actions" data-ar="الإجراءات" class="text-end">Actions</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<?php
|
||||
foreach ($data['invoices'] as $inv):
|
||||
// Fetch items for this invoice
|
||||
$items = db()->prepare("SELECT ii.*, i.name_en, i.name_ar
|
||||
FROM invoice_items ii
|
||||
JOIN stock_items i ON ii.item_id = i.id
|
||||
WHERE ii.invoice_id = ?");
|
||||
$items->execute([$inv['id']]);
|
||||
$inv['items'] = $items->fetchAll(PDO::FETCH_ASSOC);
|
||||
?>
|
||||
<tr>
|
||||
<td>INV-<?= str_pad((string)$inv['id'], 5, '0', STR_PAD_LEFT) ?></td>
|
||||
<td><?= $inv['invoice_date'] ?></td>
|
||||
<td><?= htmlspecialchars($inv['customer_name'] ?? '---') ?></td>
|
||||
<td class="text-end fw-bold">$<?= number_format((float)$inv['total_amount'], 2) ?></td>
|
||||
<td class="text-end">
|
||||
<button class="btn btn-sm btn-outline-info view-invoice-btn"
|
||||
data-json='<?= json_encode($inv, JSON_HEX_APOS | JSON_HEX_QUOT) ?>'
|
||||
data-bs-toggle="modal" data-bs-target="#viewInvoiceModal">
|
||||
<i class="bi bi-printer"></i> <span data-en="View & Print" data-ar="عرض وطباعة">View & Print</span>
|
||||
</button>
|
||||
</td>
|
||||
</tr>
|
||||
<?php endforeach; ?>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Invoice Modal -->
|
||||
<div class="modal fade" id="addInvoiceModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" data-en="Create <?= $page === 'sales' ? 'Sales' : 'Purchase' ?> Invoice" data-ar="إنشاء فاتورة <?= $page === 'sales' ? 'مبيعات' : 'مشتريات' ?>">Create <?= $page === 'sales' ? 'Sales' : 'Purchase' ?> Invoice</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form method="POST">
|
||||
<input type="hidden" name="type" value="<?= $page === 'sales' ? 'sale' : 'purchase' ?>">
|
||||
<div class="modal-body">
|
||||
<div class="row mb-4">
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" data-en="<?= $page === 'sales' ? 'Customer' : 'Supplier' ?>" data-ar="<?= $page === 'sales' ? 'العميل' : 'المورد' ?>"><?= $page === 'sales' ? 'Customer' : 'Supplier' ?></label>
|
||||
<select name="customer_id" class="form-select" required>
|
||||
<option value="">--- Select ---</option>
|
||||
<?php foreach ($data['customers_list'] as $c): ?>
|
||||
<option value="<?= $c['id'] ?>"><?= htmlspecialchars($c['name']) ?></option>
|
||||
<?php endforeach; ?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" data-en="Invoice Date" data-ar="تاريخ الفاتورة">Invoice Date</label>
|
||||
<input type="date" name="invoice_date" class="form-control" value="<?= date('Y-m-d') ?>" required>
|
||||
</div>
|
||||
<div class="col-md-4">
|
||||
<label class="form-label" data-en="Payment Type" data-ar="نوع الدفع">Payment Type</label>
|
||||
<select name="payment_type" class="form-select" required>
|
||||
<option value="cash" data-en="Cash" data-ar="نقداً">Cash</option>
|
||||
<option value="credit" data-en="Credit" data-ar="آجل">Credit</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="mb-4 position-relative">
|
||||
<label class="form-label fw-bold" data-en="Search Product (SKU / Name)" data-ar="بحث عن صنف (باركود / اسم)">Search Product (SKU / Name)</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-text"><i class="bi bi-search"></i></span>
|
||||
<input type="text" id="productSearchInput" class="form-control" placeholder="Search by SKU, Name EN or AR..." data-en="Search by SKU, Name EN or AR..." data-ar="ابحث بالباركود، الاسم الإنجليزي أو العربي...">
|
||||
</div>
|
||||
<div id="searchSuggestions" class="list-group position-absolute w-100 shadow-lg" style="z-index: 1050; display: none;"></div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table class="table table-bordered" id="invoiceItemsTable">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th style="width: 40%;" data-en="Item" data-ar="الصنف">Item</th>
|
||||
<th data-en="Quantity" data-ar="الكمية">Quantity</th>
|
||||
<th data-en="Unit Price" data-ar="سعر الوحدة">Unit Price</th>
|
||||
<th data-en="Total" data-ar="الإجمالي">Total</th>
|
||||
<th style="width: 50px;"></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="invoiceItemsTableBody">
|
||||
<!-- Rows added dynamically via search -->
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3" class="text-end fw-bold" data-en="Grand Total" data-ar="الإجمالي الكلي">Grand Total</td>
|
||||
<td class="fw-bold" id="grandTotal">$0.00</td>
|
||||
<td></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal" data-en="Cancel" data-ar="إلغاء">Cancel</button>
|
||||
<button type="submit" name="add_invoice" class="btn btn-success" data-en="Save Invoice" data-ar="حفظ الفاتورة">Save Invoice</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- View Invoice Modal (Printable) -->
|
||||
<div class="modal fade" id="viewInvoiceModal" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content border-0 shadow">
|
||||
<div class="modal-header d-print-none">
|
||||
<h5 class="modal-title" data-en="Invoice Details" data-ar="تفاصيل الفاتورة">Invoice Details</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body p-5" id="printableInvoice">
|
||||
<!-- Loaded via AJAX or static content populated by JS -->
|
||||
<div class="text-center mb-5">
|
||||
<h2 class="fw-bold text-uppercase" data-en="INVOICE" data-ar="فاتورة">INVOICE</h2>
|
||||
<div id="invoiceTypeLabel" class="badge bg-primary text-uppercase"></div>
|
||||
</div>
|
||||
|
||||
<div class="row mb-4">
|
||||
<div class="col-6">
|
||||
<h6 class="text-muted text-uppercase small" data-en="Billed To" data-ar="فاتورة إلى">Billed To</h6>
|
||||
<h5 id="invCustomerName" class="mb-1"></h5>
|
||||
<div id="invCustomerInfo" class="text-muted small"></div>
|
||||
</div>
|
||||
<div class="col-6 text-end">
|
||||
<h6 class="text-muted text-uppercase small" data-en="Invoice Details" data-ar="تفاصيل الفاتورة">Invoice Details</h6>
|
||||
<div><strong data-en="Invoice #" data-ar="رقم الفاتورة">Invoice #</strong> <span id="invNumber"></span></div>
|
||||
<div><strong data-en="Date" data-ar="التاريخ">Date:</strong> <span id="invDate"></span></div>
|
||||
<div><strong data-en="Payment" data-ar="الدفع">Payment:</strong> <span id="invPaymentType"></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<table class="table table-bordered mb-4">
|
||||
<thead class="bg-light">
|
||||
<tr>
|
||||
<th data-en="Description" data-ar="الوصف">Description</th>
|
||||
<th class="text-center" data-en="Qty" data-ar="الكمية">Qty</th>
|
||||
<th class="text-end" data-en="Price" data-ar="السعر">Price</th>
|
||||
<th class="text-end" data-en="Total" data-ar="الإجمالي">Total</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="invItemsBody">
|
||||
<!-- Items populated by JS -->
|
||||
</tbody>
|
||||
<tfoot>
|
||||
<tr>
|
||||
<td colspan="3" class="text-end fw-bold" data-en="Total" data-ar="الإجمالي">Total</td>
|
||||
<td class="text-end fw-bold" id="invGrandTotal"></td>
|
||||
</tr>
|
||||
</tfoot>
|
||||
</table>
|
||||
|
||||
<div class="mt-5 pt-5 border-top text-center text-muted small">
|
||||
<p data-en="Thank you for your business!" data-ar="شكراً لتعاملكم معنا!">Thank you for your business!</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer d-print-none">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal" data-en="Close" data-ar="إغلاق">Close</button>
|
||||
<button type="button" class="btn btn-primary" onclick="window.print()">
|
||||
<i class="bi bi-printer"></i> <span data-en="Print Invoice" data-ar="طباعة الفاتورة">Print Invoice</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<?php elseif ($page === 'payment_methods'): ?>
|
||||
<div class="card p-4">
|
||||
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||
@ -1043,6 +1434,122 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import Customers Modal -->
|
||||
<div class="modal fade" id="importCustomersModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content border-0 shadow text-start">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" data-en="Import Customers from Excel (CSV)" data-ar="استيراد العملاء من اكسل (CSV)">Import Customers from Excel (CSV)</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-info py-2">
|
||||
<small data-en="Please upload a CSV file with the following columns: Name, Email, Phone, Balance." data-ar="يرجى رفع ملف CSV بالأعمدة التالية: الاسم، البريد الإلكتروني، الهاتف، الرصيد.">
|
||||
Please upload a CSV file with the following columns: Name, Email, Phone, Balance.
|
||||
</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" data-en="Choose CSV File" data-ar="اختر ملف CSV">Choose CSV File</label>
|
||||
<input type="file" name="excel_file" class="form-control" accept=".csv" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal" data-en="Cancel" data-ar="إلغاء">Cancel</button>
|
||||
<button type="submit" name="import_customers" class="btn btn-success" data-en="Import Now" data-ar="استيراد الآن">Import Now</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import Suppliers Modal -->
|
||||
<div class="modal fade" id="importSuppliersModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content border-0 shadow text-start">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" data-en="Import Suppliers from Excel (CSV)" data-ar="استيراد الموردين من اكسل (CSV)">Import Suppliers from Excel (CSV)</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-info py-2">
|
||||
<small data-en="Please upload a CSV file with the following columns: Name, Email, Phone, Balance." data-ar="يرجى رفع ملف CSV بالأعمدة التالية: الاسم، البريد الإلكتروني، الهاتف، الرصيد.">
|
||||
Please upload a CSV file with the following columns: Name, Email, Phone, Balance.
|
||||
</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" data-en="Choose CSV File" data-ar="اختر ملف CSV">Choose CSV File</label>
|
||||
<input type="file" name="excel_file" class="form-control" accept=".csv" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal" data-en="Cancel" data-ar="إلغاء">Cancel</button>
|
||||
<button type="submit" name="import_suppliers" class="btn btn-success" data-en="Import Now" data-ar="استيراد الآن">Import Now</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import Categories Modal -->
|
||||
<div class="modal fade" id="importCategoriesModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content border-0 shadow text-start">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" data-en="Import Categories from Excel (CSV)" data-ar="استيراد الفئات من اكسل (CSV)">Import Categories from Excel (CSV)</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-info py-2">
|
||||
<small data-en="Please upload a CSV file with the following columns: Name (EN), Name (AR)." data-ar="يرجى رفع ملف CSV بالأعمدة التالية: الاسم (إنجليزي)، الاسم (عربي).">
|
||||
Please upload a CSV file with the following columns: Name (EN), Name (AR).
|
||||
</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" data-en="Choose CSV File" data-ar="اختر ملف CSV">Choose CSV File</label>
|
||||
<input type="file" name="excel_file" class="form-control" accept=".csv" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal" data-en="Cancel" data-ar="إلغاء">Cancel</button>
|
||||
<button type="submit" name="import_categories" class="btn btn-success" data-en="Import Now" data-ar="استيراد الآن">Import Now</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Import Units Modal -->
|
||||
<div class="modal fade" id="importUnitsModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
<div class="modal-content border-0 shadow text-start">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title" data-en="Import Units from Excel (CSV)" data-ar="استيراد الوحدات من اكسل (CSV)">Import Units from Excel (CSV)</h5>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<form method="POST" enctype="multipart/form-data">
|
||||
<div class="modal-body">
|
||||
<div class="alert alert-info py-2">
|
||||
<small data-en="Please upload a CSV file with the following columns: Name (EN), Name (AR), Short (EN), Short (AR)." data-ar="يرجى رفع ملف CSV بالأعمدة التالية: الاسم (إنجليزي)، الاسم (عربي)، الاختصار (إنجليزي)، الاختصار (عربي).">
|
||||
Please upload a CSV file with the following columns: Name (EN), Name (AR), Short (EN), Short (AR).
|
||||
</small>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label class="form-label" data-en="Choose CSV File" data-ar="اختر ملف CSV">Choose CSV File</label>
|
||||
<input type="file" name="excel_file" class="form-control" accept=".csv" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-light" data-bs-dismiss="modal" data-en="Cancel" data-ar="إلغاء">Cancel</button>
|
||||
<button type="submit" name="import_units" class="btn btn-success" data-en="Import Now" data-ar="استيراد الآن">Import Now</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Add Category Modal -->
|
||||
<div class="modal fade" id="addCategoryModal" tabindex="-1">
|
||||
<div class="modal-dialog">
|
||||
@ -1156,7 +1663,144 @@ document.addEventListener('DOMContentLoaded', function() {
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Invoice Form Logic
|
||||
const productSearchInput = document.getElementById('productSearchInput');
|
||||
const searchSuggestions = document.getElementById('searchSuggestions');
|
||||
const itemsTableBody = document.getElementById('invoiceItemsTableBody');
|
||||
const grandTotalEl = document.getElementById('grandTotal');
|
||||
const invoiceType = '<?= $page === "sales" ? "sale" : ($page === "purchases" ? "purchase" : "") ?>';
|
||||
|
||||
if (productSearchInput && itemsTableBody) {
|
||||
let timeout = null;
|
||||
productSearchInput.addEventListener('input', function() {
|
||||
clearTimeout(timeout);
|
||||
const q = this.value.trim();
|
||||
if (q.length < 1) {
|
||||
searchSuggestions.style.display = 'none';
|
||||
return;
|
||||
}
|
||||
|
||||
timeout = setTimeout(() => {
|
||||
fetch(`index.php?action=search_items&q=${encodeURIComponent(q)}`)
|
||||
.then(res => res.json())
|
||||
.then(data => {
|
||||
searchSuggestions.innerHTML = '';
|
||||
if (data.length > 0) {
|
||||
data.forEach(item => {
|
||||
const btn = document.createElement('button');
|
||||
btn.type = 'button';
|
||||
btn.className = 'list-group-item list-group-item-action';
|
||||
btn.innerHTML = `
|
||||
<div class="d-flex justify-content-between">
|
||||
<span><strong>${item.sku}</strong> - ${item.name_en} / ${item.name_ar}</span>
|
||||
<span class="text-muted small">Stock: ${item.stock_quantity}</span>
|
||||
</div>
|
||||
`;
|
||||
btn.onclick = () => addItemToInvoice(item);
|
||||
searchSuggestions.appendChild(btn);
|
||||
});
|
||||
searchSuggestions.style.display = 'block';
|
||||
} else {
|
||||
searchSuggestions.style.display = 'none';
|
||||
}
|
||||
});
|
||||
}, 300);
|
||||
});
|
||||
|
||||
// Close suggestions when clicking outside
|
||||
document.addEventListener('click', function(e) {
|
||||
if (!productSearchInput.contains(e.target) && !searchSuggestions.contains(e.target)) {
|
||||
searchSuggestions.style.display = 'none';
|
||||
}
|
||||
});
|
||||
|
||||
function addItemToInvoice(item) {
|
||||
searchSuggestions.style.display = 'none';
|
||||
productSearchInput.value = '';
|
||||
|
||||
// Check if item already exists in the table
|
||||
const existingRow = Array.from(itemsTableBody.querySelectorAll('.item-id-input')).find(input => input.value == item.id);
|
||||
if (existingRow) {
|
||||
const row = existingRow.closest('tr');
|
||||
const qtyInput = row.querySelector('.item-qty');
|
||||
qtyInput.value = parseFloat(qtyInput.value) + 1;
|
||||
calculateTotals();
|
||||
return;
|
||||
}
|
||||
|
||||
const row = document.createElement('tr');
|
||||
row.className = 'item-row';
|
||||
const price = invoiceType === 'sale' ? item.sale_price : item.purchase_price;
|
||||
|
||||
row.innerHTML = `
|
||||
<td>
|
||||
<input type="hidden" name="item_ids[]" class="item-id-input" value="${item.id}">
|
||||
<div><strong>${item.name_en}</strong></div>
|
||||
<div class="small text-muted">${item.name_ar} (${item.sku})</div>
|
||||
</td>
|
||||
<td><input type="number" step="0.01" name="quantities[]" class="form-control item-qty" value="1" required></td>
|
||||
<td><input type="number" step="0.01" name="prices[]" class="form-control item-price" value="${price}" required></td>
|
||||
<td><input type="number" step="0.01" class="form-control item-total" value="${price}" readonly></td>
|
||||
<td><button type="button" class="btn btn-outline-danger btn-sm remove-row"><i class="bi bi-trash"></i></button></td>
|
||||
`;
|
||||
|
||||
itemsTableBody.appendChild(row);
|
||||
attachRowListeners(row);
|
||||
calculateTotals();
|
||||
}
|
||||
|
||||
function calculateTotals() {
|
||||
let grandTotal = 0;
|
||||
itemsTableBody.querySelectorAll('.item-row').forEach(row => {
|
||||
const qty = parseFloat(row.querySelector('.item-qty').value) || 0;
|
||||
const price = parseFloat(row.querySelector('.item-price').value) || 0;
|
||||
const total = qty * price;
|
||||
row.querySelector('.item-total').value = total.toFixed(2);
|
||||
grandTotal += total;
|
||||
});
|
||||
grandTotalEl.textContent = '$' + grandTotal.toFixed(2);
|
||||
}
|
||||
|
||||
function attachRowListeners(row) {
|
||||
row.querySelector('.item-qty').addEventListener('input', calculateTotals);
|
||||
row.querySelector('.item-price').addEventListener('input', calculateTotals);
|
||||
row.querySelector('.remove-row').addEventListener('click', function() {
|
||||
row.remove();
|
||||
calculateTotals();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// View Invoice Logic
|
||||
document.querySelectorAll('.view-invoice-btn').forEach(btn => {
|
||||
btn.addEventListener('click', function() {
|
||||
const data = JSON.parse(this.dataset.json);
|
||||
document.getElementById('invNumber').textContent = 'INV-' + data.id.toString().padStart(5, '0');
|
||||
document.getElementById('invDate').textContent = data.invoice_date;
|
||||
document.getElementById('invPaymentType').textContent = data.payment_type ? data.payment_type.toUpperCase() : 'CASH';
|
||||
document.getElementById('invCustomerName').textContent = data.customer_name || '---';
|
||||
document.getElementById('invoiceTypeLabel').textContent = data.type;
|
||||
document.getElementById('invoiceTypeLabel').className = 'badge text-uppercase ' + (data.type === 'sale' ? 'bg-success' : 'bg-warning');
|
||||
|
||||
const body = document.getElementById('invItemsBody');
|
||||
body.innerHTML = '';
|
||||
data.items.forEach(item => {
|
||||
const tr = document.createElement('tr');
|
||||
tr.innerHTML = `
|
||||
<td>${item.name_en} / ${item.name_ar}</td>
|
||||
<td class="text-center">${item.quantity}</td>
|
||||
<td class="text-end">$${parseFloat(item.unit_price).toFixed(2)}</td>
|
||||
<td class="text-end">$${parseFloat(item.total_price).toFixed(2)}</td>
|
||||
`;
|
||||
body.appendChild(tr);
|
||||
});
|
||||
document.getElementById('invGrandTotal').textContent = '$' + parseFloat(data.total_amount).toFixed(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user