false, 'error' => 'Access Denied']); exit; } die('Access Denied'); } if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) { $action = $_POST['action']; if ($action === 'add_item') { $name_en = $_POST['name_en']; $name_ar = $_POST['name_ar']; $category_id = $_POST['category_id'] ?: null; $vat_percent = (float)($_POST['vat_percent'] ?? 15.00); $image_url = null; // Handle Image Upload if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) { $ext = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION); $filename = 'item_' . uniqid('', true) . '.' . $ext; $upload_dir = __DIR__ . '/assets/images/items/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0775, true); if (move_uploaded_file($_FILES['image']['tmp_name'], $upload_dir . $filename)) { $image_url = 'assets/images/items/' . $filename; } } $stmt = db()->prepare("INSERT INTO items (name_en, name_ar, category_id, vat_percent, image_url) VALUES (?, ?, ?, ?, ?)"); $stmt->execute([$name_en, $name_ar, $category_id, $vat_percent, $image_url]); header('Location: items.php?success=item_added'); exit; } elseif ($action === 'edit_item') { $id = $_POST['id']; $name_en = $_POST['name_en']; $name_ar = $_POST['name_ar']; $category_id = $_POST['category_id'] ?: null; $vat_percent = (float)($_POST['vat_percent'] ?? 15.00); $image_url = $_POST['current_image_url'] ?? null; // Handle Image Upload if (isset($_FILES['image']) && $_FILES['image']['error'] === UPLOAD_ERR_OK) { $ext = pathinfo($_FILES['image']['name'], PATHINFO_EXTENSION); $filename = 'item_' . uniqid('', true) . '.' . $ext; $upload_dir = __DIR__ . '/assets/images/items/'; if (!is_dir($upload_dir)) mkdir($upload_dir, 0775, true); if (move_uploaded_file($_FILES['image']['tmp_name'], $upload_dir . $filename)) { $image_url = 'assets/images/items/' . $filename; } } $stmt = db()->prepare("UPDATE items SET name_en = ?, name_ar = ?, category_id = ?, vat_percent = ?, image_url = ? WHERE id = ?"); $stmt->execute([$name_en, $name_ar, $category_id, $vat_percent, $image_url, $id]); header('Location: items.php?success=item_updated'); exit; } elseif ($action === 'delete_item') { $id = $_POST['id']; try { $stmt = db()->prepare("DELETE FROM items WHERE id = ?"); $stmt->execute([$id]); header('Location: items.php?success=item_deleted'); exit; } catch (PDOException $e) { header('Location: items.php?error=cannot_delete_item'); exit; } } elseif ($action === 'add_category') { $name_en = $_POST['cat_name_en']; $name_ar = $_POST['cat_name_ar']; $stmt = db()->prepare("INSERT INTO categories (name_en, name_ar) VALUES (?, ?)"); $stmt->execute([$name_en, $name_ar]); if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => true, 'html' => renderCategoryList($lang)]); exit; } header('Location: items.php?success=category_added'); exit; } elseif ($action === 'edit_category') { $id = $_POST['id']; $name_en = $_POST['cat_name_en']; $name_ar = $_POST['cat_name_ar']; $stmt = db()->prepare("UPDATE categories SET name_en = ?, name_ar = ? WHERE id = ?"); $stmt->execute([$name_en, $name_ar, $id]); if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => true, 'html' => renderCategoryList($lang)]); exit; } header('Location: items.php?success=category_updated'); exit; } elseif ($action === 'delete_category') { $id = $_POST['id']; try { // Before deleting category, set items to null category $stmt = db()->prepare("UPDATE items SET category_id = NULL WHERE category_id = ?"); $stmt->execute([$id]); $stmt = db()->prepare("DELETE FROM categories WHERE id = ?"); $stmt->execute([$id]); if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => true, 'html' => renderCategoryList($lang)]); exit; } header('Location: items.php?success=category_deleted'); exit; } catch (PDOException $e) { if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => false, 'error' => 'Cannot delete category.']); exit; } header('Location: items.php?error=cannot_delete_category'); exit; } } elseif ($action === 'add_service') { $name_en = $_POST['svc_name_en']; $name_ar = $_POST['svc_name_ar']; $stmt = db()->prepare("INSERT INTO services (name_en, name_ar) VALUES (?, ?)"); $stmt->execute([$name_en, $name_ar]); if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => true, 'html' => renderServiceList($lang)]); exit; } header('Location: items.php?success=service_added'); exit; } elseif ($action === 'edit_service') { $id = $_POST['id']; $name_en = $_POST['svc_name_en']; $name_ar = $_POST['svc_name_ar']; $stmt = db()->prepare("UPDATE services SET name_en = ?, name_ar = ? WHERE id = ?"); $stmt->execute([$name_en, $name_ar, $id]); if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => true, 'html' => renderServiceList($lang)]); exit; } header('Location: items.php?success=service_updated'); exit; } elseif ($action === 'delete_service') { $id = $_POST['id']; try { $stmt = db()->prepare("DELETE FROM services WHERE id = ?"); $stmt->execute([$id]); if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => true, 'html' => renderServiceList($lang)]); exit; } header('Location: items.php?success=service_deleted'); exit; } catch (PDOException $e) { $stmt = db()->prepare("UPDATE services SET is_deleted = 1 WHERE id = ?"); $stmt->execute([$id]); if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => true, 'html' => renderServiceList($lang)]); exit; } header('Location: items.php?success=service_deleted'); exit; } } elseif ($action === 'update_price') { $item_id = $_POST['item_id']; $service_id = $_POST['service_id']; $price = $_POST['price']; // Handle deletion if price is empty if ($price === '') { try { // Delete ALL prices (both global and branch-specific) for this item and service. // The user clicking "X" intends to remove this service from the item entirely. $stmt = db()->prepare("DELETE FROM prices WHERE item_id = ? AND service_id = ?"); $stmt->execute([$item_id, $service_id]); if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => true]); exit; } header('Location: items.php?success=price_deleted'); exit; } catch (Exception $e) { if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => false, 'error' => $e->getMessage()]); exit; } header('Location: items.php?error=delete_failed'); exit; } } $price = str_replace(',', '.', $price); // Handle comma as decimal separator $price = (float)$price; try { // Prices are globally shared $chk = db()->prepare("SELECT id FROM prices WHERE item_id = ? AND service_id = ?"); $chk->execute([$item_id, $service_id]); $existing = $chk->fetch(); if ($existing) { $stmt = db()->prepare("UPDATE prices SET price = ?, branch_id = NULL WHERE id = ?"); $stmt->execute([$price, $existing['id']]); } else { $stmt = db()->prepare("INSERT INTO prices (item_id, service_id, price, branch_id) VALUES (?, ?, ?, NULL)"); $stmt->execute([$item_id, $service_id, $price]); } if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => true]); exit; } header('Location: items.php?success=price_updated'); exit; } catch (Exception $e) { if ($isAjax) { header('Content-Type: application/json'); echo json_encode(['success' => false, 'error' => $e->getMessage()]); exit; } header('Location: items.php?error=save_failed'); exit; } } } // NOW Include header $title = 'items'; require_once __DIR__ . '/includes/header.php'; // Search and Category Filter $search = $_GET['search'] ?? ''; $cat_id = $_GET['category_id'] ?? ''; $current_branch_id = $_SESSION['branch_id'] ?? null; // Fetch categories $categories = db()->query("SELECT * FROM categories WHERE is_deleted = 0 ORDER BY name_en ASC")->fetchAll(); // Fetch services $services = db()->query("SELECT * FROM services WHERE is_deleted = 0 ORDER BY name_en ASC")->fetchAll(); // Fetch items with filters $where = []; $params = []; if ($search) { $where[] = "(name_en LIKE ? OR name_ar LIKE ?)"; $params[] = "%$search%"; $params[] = "%$search%"; } if ($cat_id) { $where[] = "category_id = ?"; $params[] = $cat_id; } $where[] = "is_deleted = 0"; $where_sql = $where ? "WHERE " . implode(" AND ", $where) : ""; $stmt = db()->prepare("SELECT * FROM items $where_sql ORDER BY name_en ASC"); $stmt->execute($params); $items = $stmt->fetchAll(); // Fetch prices (globally shared) $stmt = db()->prepare("SELECT * FROM prices"); $stmt->execute(); $prices_raw = $stmt->fetchAll(); $prices = []; foreach ($prices_raw as $p) { $prices[$p['item_id']][$p['service_id']] = $p['price']; } function renderCategoryList($lang) { $categories = db()->query("SELECT * FROM categories WHERE is_deleted = 0 ORDER BY name_en ASC")->fetchAll(); ob_start(); foreach($categories as $cat): ?>
= __('manage_items_categories_services') ?? 'Manage your items, categories and services' ?>
= __('no_items_found') ?>