- true, 'html' => $html]);
+ echo json_encode(['success' => true, 'html' => renderCategoryList($lang)]);
exit;
}
header('Location: items.php?success=category_added');
@@ -46,103 +97,36 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if ($isAjax) {
header('Content-Type: application/json');
- $categories = db()->query("SELECT * FROM categories ORDER BY name_en ASC")->fetchAll();
- ob_start();
- foreach($categories as $cat): ?>
-
-
= $cat['name_en'] ?>
-
= $cat['name_ar'] ?>
-
-
-
-
-
- true, 'html' => $html]);
+ echo json_encode(['success' => true, 'html' => renderCategoryList($lang)]);
exit;
}
header('Location: items.php?success=category_updated');
exit;
} elseif ($action === 'delete_category') {
$id = $_POST['id'];
- $stmt = db()->prepare("DELETE FROM categories WHERE id = ?");
- $stmt->execute([$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');
- $categories = db()->query("SELECT * FROM categories ORDER BY name_en ASC")->fetchAll();
- ob_start();
- foreach($categories as $cat): ?>
-
-
= $cat['name_en'] ?>
-
= $cat['name_ar'] ?>
-
-
-
-
-
- true, 'html' => $html]);
+ 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;
}
- header('Location: items.php?success=category_deleted');
- exit;
- } elseif ($action === 'add_item') {
- $category_id = $_POST['category_id'] ?: null;
- $name_en = $_POST['name_en'];
- $name_ar = $_POST['name_ar'];
- $vat_percent = $_POST['vat_percent'] ?: 0;
-
- $image_url = null;
- if (isset($_FILES['image']) && $_FILES['image']['error'] === 0) {
- $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, 0777, true);
- if (move_uploaded_file($_FILES['image']['tmp_name'], $upload_dir . $filename)) {
- $image_url = 'assets/images/items/' . $filename;
- }
- }
-
- $stmt = db()->prepare("INSERT INTO items (category_id, name_en, name_ar, vat_percent, image_url) VALUES (?, ?, ?, ?, ?)");
- $stmt->execute([$category_id, $name_en, $name_ar, $vat_percent, $image_url]);
- header('Location: items.php?success=item_added');
- exit;
- } elseif ($action === 'edit_item') {
- $id = $_POST['id'];
- $category_id = $_POST['category_id'] ?: null;
- $name_en = $_POST['name_en'];
- $name_ar = $_POST['name_ar'];
- $vat_percent = $_POST['vat_percent'] ?: 0;
-
- $image_url = null;
- if (isset($_FILES['image']) && $_FILES['image']['error'] === 0) {
- $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, 0777, true);
- if (move_uploaded_file($_FILES['image']['tmp_name'], $upload_dir . $filename)) {
- $image_url = 'assets/images/items/' . $filename;
- }
- }
-
- if ($image_url) {
- $stmt = db()->prepare("UPDATE items SET category_id = ?, name_en = ?, name_ar = ?, vat_percent = ?, image_url = ? WHERE id = ?");
- $stmt->execute([$category_id, $name_en, $name_ar, $vat_percent, $image_url, $id]);
- } else {
- $stmt = db()->prepare("UPDATE items SET category_id = ?, name_en = ?, name_ar = ?, vat_percent = ? WHERE id = ?");
- $stmt->execute([$category_id, $name_en, $name_ar, $vat_percent, $id]);
- }
- header('Location: items.php?success=item_updated');
- exit;
- } elseif ($action === 'delete_item') {
- $id = $_POST['id'];
- $stmt = db()->prepare("DELETE FROM items WHERE id = ?");
- $stmt->execute([$id]);
- header('Location: items.php?success=item_deleted');
- exit;
} elseif ($action === 'add_service') {
$name_en = $_POST['svc_name_en'];
$name_ar = $_POST['svc_name_ar'];
@@ -172,16 +156,28 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
exit;
} elseif ($action === 'delete_service') {
$id = $_POST['id'];
- $stmt = db()->prepare("DELETE FROM services WHERE id = ?");
- $stmt->execute([$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)]);
+ 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;
}
- header('Location: items.php?success=service_deleted');
- exit;
} elseif ($action === 'update_price') {
$item_id = $_POST['item_id'];
$service_id = $_POST['service_id'];
@@ -201,19 +197,10 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
// Handle deletion if price is empty
if ($price === '') {
try {
- if ($branch_id) {
- // Delete branch-specific price
- $stmt = db()->prepare("DELETE FROM prices WHERE item_id = ? AND service_id = ? AND branch_id = ?");
- $stmt->execute([$item_id, $service_id, $branch_id]);
-
- // Also try to delete global price if it's the one currently showing or if we want it completely gone
- // Most users expect that clicking "Delete" removes the item/service association they see.
- $stmtGlobal = db()->prepare("DELETE FROM prices WHERE item_id = ? AND service_id = ? AND branch_id IS NULL");
- $stmtGlobal->execute([$item_id, $service_id]);
- } else {
- $stmt = db()->prepare("DELETE FROM prices WHERE item_id = ? AND service_id = ? AND branch_id IS NULL");
- $stmt->execute([$item_id, $service_id]);
- }
+ // 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');
@@ -284,46 +271,40 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$title = 'items';
require_once __DIR__ . '/includes/header.php';
-// Filter logic
+// Search and Category Filter
$search = $_GET['search'] ?? '';
-$category_filter = $_GET['category_id'] ?? '';
+$cat_id = $_GET['category_id'] ?? '';
-$categories = db()->query("SELECT * FROM categories ORDER BY name_en ASC")->fetchAll();
+$current_branch_id = $_SESSION['branch_id'] ?? null;
-$query = "SELECT i.*, c.name_en as cat_en, c.name_ar as cat_ar
- FROM items i
- LEFT JOIN categories c ON i.category_id = c.id";
-$params = [];
+// 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[] = "(i.name_en LIKE ? OR i.name_ar LIKE ?)";
+ $where[] = "(name_en LIKE ? OR name_ar LIKE ?)";
$params[] = "%$search%";
$params[] = "%$search%";
}
-
-if ($category_filter) {
- $where[] = "i.category_id = ?";
- $params[] = $category_filter;
+if ($cat_id) {
+ $where[] = "category_id = ?";
+ $params[] = $cat_id;
}
-if ($where) {
- $query .= " WHERE " . implode(" AND ", $where);
-}
-
-$query .= " ORDER BY i.name_en ASC";
-$stmt = db()->prepare($query);
+ $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();
-$services = db()->query("SELECT * FROM services ORDER BY name_en ASC")->fetchAll();
-
-// Fetch prices based on current branch
-$current_branch_id = $_SESSION['branch_id'] ?? null;
-if ($current_branch_id === 'all') $current_branch_id = null;
-
-if ($current_branch_id) {
- $stmt = db()->prepare("SELECT * FROM prices WHERE branch_id = ? OR branch_id IS NULL ORDER BY branch_id DESC"); // Branch-specific first
+// Fetch prices
+if ($current_branch_id && $current_branch_id !== 'all') {
+ $stmt = db()->prepare("SELECT * FROM prices WHERE branch_id = ? OR branch_id IS NULL ORDER BY branch_id DESC");
$stmt->execute([$current_branch_id]);
} else {
$stmt = db()->prepare("SELECT * FROM prices WHERE branch_id IS NULL");
@@ -338,8 +319,24 @@ foreach ($prices_raw as $p) {
}
}
+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): ?>
+
+
= $cat['name_en'] ?>
+
= $cat['name_ar'] ?>
+
+
+
+
+
+ query("SELECT * FROM services ORDER BY name_en ASC")->fetchAll();
+ $services = db()->query("SELECT * FROM services WHERE is_deleted = 0 ORDER BY name_en ASC")->fetchAll();
ob_start();
foreach($services as $svc): ?>
@@ -375,154 +372,178 @@ function renderServiceList($lang) {
-
-
-
+
\ No newline at end of file
diff --git a/orders.php b/orders.php
index dcf0abc..097bce7 100644
--- a/orders.php
+++ b/orders.php
@@ -108,25 +108,26 @@ if ($current_role === 'super_admin') {
-
-
-
-
+
+
+
+
+
@@ -134,15 +135,15 @@ if ($current_role === 'super_admin') {
-
#
-
= __('order_number') ?? 'Order #' ?>
+
ID
+
= __('order_number') ?>
= __('branch') ?>
= __('customer') ?>
+
= __('subtotal') ?>
+
= __('loyalty_discount') ?>
= __('total') ?>
-
= __('loyalty_discount') ?? 'Loyalty Discount' ?>
-
= __('final_total') ?? 'Final Total' ?>
= __('status') ?>
= __('payment_status') ?>
= __('date') ?>
@@ -165,7 +166,7 @@ if ($current_role === 'super_admin') {