query("SELECT sku, name, price, cost_price, base_stock, vat, category_id, supplier_id, unit_id FROM items ORDER BY id DESC"); $items = $stmt->fetchAll(PDO::FETCH_ASSOC); header('Content-Type: text/csv; charset=utf-8'); header('Content-Disposition: attachment; filename=stock_export_' . date('Ymd_His') . '.csv'); echo ""; $output = fopen('php://output', 'w'); fputcsv($output, ['SKU', 'Name', 'Price', 'Cost Price', 'Stock', 'VAT', 'Category ID', 'Supplier ID', 'Unit ID']); foreach ($items as $row) { fputcsv($output, $row); } fclose($output); exit; } // Handle Import CSV if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'import_csv') { if (isset($_FILES['csv_file']) && $_FILES['csv_file']['error'] === UPLOAD_ERR_OK) { $pdo = db(); $file = fopen($_FILES['csv_file']['tmp_name'], 'r'); $bom = fread($file, 3); if ($bom !== "") rewind($file); $header = fgetcsv($file); $imported = 0; $updated = 0; $pdo->beginTransaction(); try { $stmtInsert = $pdo->prepare("INSERT INTO items (sku, name, price, cost_price, base_stock, vat, category_id, supplier_id, unit_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmtUpdate = $pdo->prepare("UPDATE items SET name=?, price=?, cost_price=?, base_stock=?, vat=?, category_id=?, supplier_id=?, unit_id=? WHERE sku=?"); $stmtCheck = $pdo->prepare("SELECT id FROM items WHERE sku=?"); while (($row = fgetcsv($file)) !== false) { if (count($row) < 5) continue; $sku = trim($row[0]); $name = trim($row[1]); if ($sku === '' || $name === '') continue; $price = (float)($row[2] ?? 0); $cost_price = (float)($row[3] ?? 0); $base_stock = (int)($row[4] ?? 0); $vat = (float)($row[5] ?? 5); $category_id = !empty($row[6]) ? (int)$row[6] : null; $supplier_id = !empty($row[7]) ? (int)$row[7] : null; $unit_id = !empty($row[8]) ? (int)$row[8] : null; $stmtCheck->execute([$sku]); if ($stmtCheck->fetchColumn()) { $stmtUpdate->execute([$name, $price, $cost_price, $base_stock, $vat, $category_id, $supplier_id, $unit_id, $sku]); $updated++; } else { $stmtInsert->execute([$sku, $name, $price, $cost_price, $base_stock, $vat, $category_id, $supplier_id, $unit_id]); $imported++; } } $pdo->commit(); header('Location: stock.php?import_success=1&imported='.$imported.'&updated='.$updated); exit; } catch (Exception $e) { $pdo->rollBack(); header('Location: stock.php?import_error='.urlencode($e->getMessage())); exit; } } header('Location: stock.php?import_error=No+file'); exit; } // Handle AJAX actions if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { header('Content-Type: application/json'); $pdo = db(); if ($_POST['action'] === 'save') { try { $sku = $_POST['sku'] ?? ''; $name = $_POST['name'] ?? ''; $price = (float)($_POST['price'] ?? 0); $cost_price = (float)($_POST['cost_price'] ?? 0); $base_stock = (int)($_POST['base_stock'] ?? 0); $vat = (float)($_POST['vat'] ?? get_setting('vat_percentage', 5)); $category_id = !empty($_POST['category_id']) ? (int)$_POST['category_id'] : null; $supplier_id = !empty($_POST['supplier_id']) ? (int)$_POST['supplier_id'] : null; $unit_id = !empty($_POST['unit_id']) ? (int)$_POST['unit_id'] : null; if (!$sku || !$name) { echo json_encode(['success' => false, 'error' => 'Missing SKU or Name']); exit; } $image_url = $_POST['existing_image_url'] ?? null; if (isset($_FILES['picture']) && $_FILES['picture']['error'] === UPLOAD_ERR_OK) { $uploadDir = __DIR__ . '/assets/images/items/'; if (!is_dir($uploadDir)) { mkdir($uploadDir, 0775, true); } $ext = pathinfo($_FILES['picture']['name'], PATHINFO_EXTENSION); $filename = time() . '_' . rand(1000, 9999) . '.' . $ext; if (move_uploaded_file($_FILES['picture']['tmp_name'], $uploadDir . $filename)) { $image_url = 'assets/images/items/' . $filename; } } $stmt = $pdo->prepare('SELECT id FROM items WHERE sku = ?'); $stmt->execute([$sku]); $existing = $stmt->fetch(); if (isset($_POST['original_sku']) && $_POST['original_sku'] !== '') { $orig_sku = $_POST['original_sku']; if ($existing && $existing['id'] != ($pdo->query("SELECT id FROM items WHERE sku = " . $pdo->quote($orig_sku))->fetchColumn() ?: -1)) { echo json_encode(['success' => false, 'error' => 'SKU already exists']); exit; } $sql = "UPDATE items SET sku=?, name=?, price=?, cost_price=?, base_stock=?, vat=?, category_id=?, supplier_id=?, unit_id=? " . ($image_url ? ", image_url=?" : "") . " WHERE sku=?"; $params = [$sku, $name, $price, $cost_price, $base_stock, $vat, $category_id, $supplier_id, $unit_id]; if ($image_url) { $params[] = $image_url; } $params[] = $orig_sku; $stmt = $pdo->prepare($sql); $stmt->execute($params); } else { if ($existing) { echo json_encode(['success' => false, 'error' => 'SKU already exists']); exit; } $stmt = $pdo->prepare("INSERT INTO items (sku, name, price, cost_price, base_stock, vat, category_id, supplier_id, unit_id, image_url) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"); $stmt->execute([$sku, $name, $price, $cost_price, $base_stock, $vat, $category_id, $supplier_id, $unit_id, $image_url]); } echo json_encode(['success' => true]); exit; } catch (Throwable $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); exit; } } if ($_POST['action'] === 'delete') { try { $sku = $_POST['sku'] ?? ''; if (!$sku) { echo json_encode(['success' => false, 'error' => 'Missing SKU']); exit; } $stmt = $pdo->prepare('DELETE FROM items WHERE sku = ?'); $stmt->execute([$sku]); echo json_encode(['success' => true]); exit; } catch (Throwable $e) { echo json_encode(['success' => false, 'error' => $e->getMessage()]); exit; } } } $allStock = []; try { $allStock = stock_snapshot(); } catch (Throwable $e) { $dbError = $e->getMessage(); } $categories = []; $suppliers = []; try { $pdo = db(); $categories = $pdo->query('SELECT id, name_ar, name_en FROM categories ORDER BY name_ar ASC')->fetchAll(); $suppliers = $pdo->query('SELECT id, name FROM suppliers ORDER BY name ASC')->fetchAll(); $units = $pdo->query('SELECT id, name_ar, name_en FROM units ORDER BY name_ar ASC')->fetchAll(); } catch (Throwable $e) { // Ignore if not present } // Search and filter logic $search = $_GET['q'] ?? ''; $catFilter = $_GET['category'] ?? ''; $supFilter = $_GET['supplier'] ?? ''; $filteredStock = []; if (empty($dbError)) { $lowerSearch = strtolower($search); foreach ($allStock as $key => $row) { $matchSearch = !$search || str_contains(strtolower((string)$row['sku']), $lowerSearch) || str_contains(strtolower((string)$row['name']), $lowerSearch); $matchCat = !$catFilter || (isset($row['category_id']) && $row['category_id'] == $catFilter); $matchSup = !$supFilter || (isset($row['supplier_id']) && $row['supplier_id'] == $supFilter); if ($matchSearch && $matchCat && $matchSup) { $filteredStock[$key] = $row; } } } // Pagination logic $page = max(1, (int)($_GET['p'] ?? 1)); $limit = 10; $total = count($filteredStock); $totalPages = max(1, ceil($total / $limit)); $offset = ($page - 1) * $limit; $stockRows = array_slice($filteredStock, $offset, $limit, true); require __DIR__ . '/includes/header.php'; ?>

" . $import_success_message . "
"; endif; ?> " . $import_error_message . ""; endif; ?>
SKU
pic
1): ?>