diff --git a/admin/includes/header.php b/admin/includes/header.php index cb8e907..66e8ad5 100644 --- a/admin/includes/header.php +++ b/admin/includes/header.php @@ -401,7 +401,7 @@ function can_view($module) { @@ -415,7 +415,7 @@ function can_view($module) { diff --git a/admin/profile.php b/admin/profile.php index c464fee..772aae7 100644 --- a/admin/profile.php +++ b/admin/profile.php @@ -7,17 +7,21 @@ $pdo = db(); $currentUser = get_logged_user(); $id = $currentUser['id']; -// Always fetch fresh data from DB -$stmt = $pdo->prepare("SELECT u.*, g.name as group_name, g.permissions - FROM users u - LEFT JOIN user_groups g ON u.group_id = g.id - WHERE u.id = ?"); -$stmt->execute([$id]); -$user = $stmt->fetch(PDO::FETCH_ASSOC); +// Helper for fresh data +function fetch_user_data($pdo, $id) { + $stmt = $pdo->prepare("SELECT u.*, g.name as group_name, g.permissions + FROM users u + LEFT JOIN user_groups g ON u.group_id = g.id + WHERE u.id = ?"); + $stmt->execute([$id]); + return $stmt->fetch(PDO::FETCH_ASSOC); +} + +$user = fetch_user_data($pdo, $id); if (!$user) { logout_user(); - header('Location: /login.php'); + header('Location: ' . get_base_url() . 'login.php'); exit; } @@ -25,12 +29,13 @@ $message = ''; if ($_SERVER['REQUEST_METHOD'] === 'POST') { $full_name = $_POST['full_name']; + $full_name_ar = $_POST['full_name_ar'] ?? ''; $email = $_POST['email']; $pdo->beginTransaction(); try { - $sql = "UPDATE users SET full_name = ?, email = ? WHERE id = ?"; - $params = [$full_name, $email, $id]; + $sql = "UPDATE users SET full_name = ?, full_name_ar = ?, email = ? WHERE id = ?"; + $params = [$full_name, $full_name_ar, $email, $id]; $stmt = $pdo->prepare($sql); $stmt->execute($params); @@ -73,13 +78,14 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $message = '
Profile updated successfully!
'; // Refresh user data and update session - $stmt->execute([$id]); - $user = $stmt->fetch(PDO::FETCH_ASSOC); + $user = fetch_user_data($pdo, $id); $_SESSION['user'] = $user; unset($_SESSION['user']['password']); } catch (Exception $e) { - $pdo->rollBack(); + if ($pdo->inTransaction()) { + $pdo->rollBack(); + } $message = '
Error updating profile: ' . $e->getMessage() . '
'; } } @@ -101,24 +107,38 @@ include 'includes/header.php';
- - + +
- - + +
+ + +
- - + +
+
+ + +
+
+ +
- - + +
+
+
@@ -131,7 +151,7 @@ include 'includes/header.php'; Profile Picture
- +
@@ -165,19 +185,19 @@ include 'includes/header.php'; Profile Picture
- +
-

-
@
+

+
@
Active Account
- Member since + Member since
@@ -195,4 +215,35 @@ include 'includes/header.php'; + + \ No newline at end of file diff --git a/admin/purchase_edit.php b/admin/purchase_edit.php deleted file mode 100644 index a43b880..0000000 --- a/admin/purchase_edit.php +++ /dev/null @@ -1,352 +0,0 @@ -prepare("SELECT * FROM purchases WHERE id = ?"); - $stmt->execute([$id]); - $purchase = $stmt->fetch(); - - if (!$purchase) { - header("Location: purchases.php"); - exit; - } - - $stmt = $pdo->prepare("SELECT pi.*, p.name as product_name FROM purchase_items pi JOIN products p ON pi.product_id = p.id WHERE pi.purchase_id = ?"); - $stmt->execute([$id]); - $items = $stmt->fetchAll(); -} - -if ($_SERVER['REQUEST_METHOD'] === 'POST') { - $supplier_id = $_POST['supplier_id'] ?: null; - $purchase_date = $_POST['purchase_date']; - $status = $_POST['status']; - $notes = $_POST['notes']; - $product_ids = $_POST['product_id'] ?? []; - $quantities = $_POST['quantity'] ?? []; - $cost_prices = $_POST['cost_price'] ?? []; - - try { - $pdo->beginTransaction(); - - $total_amount = 0; - foreach ($product_ids as $index => $pid) { - $total_amount += $quantities[$index] * $cost_prices[$index]; - } - - if ($id) { - $old_status = $purchase['status']; - $stmt = $pdo->prepare("UPDATE purchases SET supplier_id = ?, purchase_date = ?, status = ?, notes = ?, total_amount = ? WHERE id = ?"); - $stmt->execute([$supplier_id, $purchase_date, $status, $notes, $total_amount, $id]); - - $stmt = $pdo->prepare("SELECT * FROM purchase_items WHERE purchase_id = ?"); - $stmt->execute([$id]); - $old_items = $stmt->fetchAll(); - - if ($old_status === 'completed') { - foreach ($old_items as $oi) { - $pdo->prepare("UPDATE products SET stock_quantity = stock_quantity - ? WHERE id = ?") - ->execute([$oi['quantity'], $oi['product_id']]); - } - } - $pdo->prepare("DELETE FROM purchase_items WHERE purchase_id = ?")->execute([$id]); - } else { - $stmt = $pdo->prepare("INSERT INTO purchases (supplier_id, purchase_date, status, notes, total_amount) VALUES (?, ?, ?, ?, ?)"); - $stmt->execute([$supplier_id, $purchase_date, $status, $notes, $total_amount]); - $id = $pdo->lastInsertId(); - } - - foreach ($product_ids as $index => $pid) { - $qty = $quantities[$index]; - $cost = $cost_prices[$index]; - $total_item_price = $qty * $cost; - - $stmt = $pdo->prepare("INSERT INTO purchase_items (purchase_id, product_id, quantity, cost_price, total_price) VALUES (?, ?, ?, ?, ?)"); - $stmt->execute([$id, $pid, $qty, $cost, $total_item_price]); - - if ($status === 'completed') { - $pdo->prepare("UPDATE products SET stock_quantity = stock_quantity + ?, cost_price = ? WHERE id = ?") - ->execute([$qty, $cost, $pid]); - } - } - - $pdo->commit(); - header("Location: purchases.php?msg=success"); - exit; - } catch (Exception $e) { - $pdo->rollBack(); - $message = '
Error: ' . $e->getMessage() . '
'; - } -} - -$suppliers = $pdo->query("SELECT * FROM suppliers ORDER BY name")->fetchAll(); -$products = $pdo->query("SELECT id, name, cost_price FROM products ORDER BY name")->fetchAll(); -$products_json = json_encode($products); - -include 'includes/header.php'; -?> - -
-
- Back to Purchases -

-
-
- - - - -
-
-
-
-
Purchase Details
-
-
- - -
-
- - -
-
- - -
-
- - -
-
-
-
- -
-
-
-
Products to Purchase
-
-
- - -
- -
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
PRODUCTQTYCOSTTOTAL
-
- -
Grand Total:
- -
-
-
Use the search bar above to add products to this purchase.
-
-
-
-
- -
- -
-
-
-
- - - - - - \ No newline at end of file diff --git a/admin/purchases.php b/admin/purchases.php index 0853222..4b07aa6 100644 --- a/admin/purchases.php +++ b/admin/purchases.php @@ -6,18 +6,95 @@ $pdo = db(); $message = ''; +// Handle SAVE (Add/Edit) Purchase via POST +if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action']) && $_POST['action'] === 'save_purchase') { + $id = $_POST['id'] ?: null; + $supplier_id = $_POST['supplier_id'] ?: null; + $purchase_date = $_POST['purchase_date']; + $status = $_POST['status']; + $notes = $_POST['notes']; + $product_ids = $_POST['product_id'] ?? []; + $quantities = $_POST['quantity'] ?? []; + $cost_prices = $_POST['cost_price'] ?? []; + + try { + $pdo->beginTransaction(); + + $total_amount = 0; + foreach ($product_ids as $index => $pid) { + $total_amount += $quantities[$index] * $cost_prices[$index]; + } + + $purchase = null; + if ($id) { + $stmt = $pdo->prepare("SELECT * FROM purchases WHERE id = ?"); + $stmt->execute([$id]); + $purchase = $stmt->fetch(); + + if ($purchase) { + $old_status = $purchase['status']; + $stmt = $pdo->prepare("UPDATE purchases SET supplier_id = ?, purchase_date = ?, status = ?, notes = ?, total_amount = ? WHERE id = ?"); + $stmt->execute([$supplier_id, $purchase_date, $status, $notes, $total_amount, $id]); + + $stmt = $pdo->prepare("SELECT * FROM purchase_items WHERE purchase_id = ?"); + $stmt->execute([$id]); + $old_items = $stmt->fetchAll(); + + if ($old_status === 'completed') { + foreach ($old_items as $oi) { + $pdo->prepare("UPDATE products SET stock_quantity = stock_quantity - ? WHERE id = ?") + ->execute([$oi['quantity'], $oi['product_id']]); + } + } + $pdo->prepare("DELETE FROM purchase_items WHERE purchase_id = ?")->execute([$id]); + } + } else { + $stmt = $pdo->prepare("INSERT INTO purchases (supplier_id, purchase_date, status, notes, total_amount) VALUES (?, ?, ?, ?, ?)"); + $stmt->execute([$supplier_id, $purchase_date, $status, $notes, $total_amount]); + $id = $pdo->lastInsertId(); + } + + foreach ($product_ids as $index => $pid) { + $qty = $quantities[$index]; + $cost = $cost_prices[$index]; + $total_item_price = $qty * $cost; + + $stmt = $pdo->prepare("INSERT INTO purchase_items (purchase_id, product_id, quantity, cost_price, total_price) VALUES (?, ?, ?, ?, ?)"); + $stmt->execute([$id, $pid, $qty, $cost, $total_item_price]); + + if ($status === 'completed') { + $pdo->prepare("UPDATE products SET stock_quantity = stock_quantity + ?, cost_price = ? WHERE id = ?") + ->execute([$qty, $cost, $pid]); + } + } + + $pdo->commit(); + $message = ''; + } catch (Exception $e) { + $pdo->rollBack(); + $message = '
Error: ' . $e->getMessage() . '
'; + } +} + +// Handle Delete if (isset($_GET['delete'])) { if (!has_permission('purchases_del')) { $message = '
Access Denied: You do not have permission to delete purchases.
'; } else { $id = $_GET['delete']; $pdo->prepare("DELETE FROM purchases WHERE id = ?")->execute([$id]); - header("Location: purchases.php"); + header("Location: purchases.php?msg=deleted"); exit; } } +if (isset($_GET['msg']) && $_GET['msg'] === 'deleted') { + $message = ''; +} + $suppliers = $pdo->query("SELECT * FROM suppliers ORDER BY name")->fetchAll(); +$products = $pdo->query("SELECT id, name, cost_price FROM products ORDER BY name")->fetchAll(); +$products_json = json_encode($products); $search = $_GET['search'] ?? ''; $supplier_filter = $_GET['supplier_filter'] ?? ''; @@ -63,9 +140,9 @@ include 'includes/header.php';

Manage restocks, supplier invoices and inventory tracking

- + @@ -143,9 +220,9 @@ include 'includes/header.php';
- + @@ -176,4 +253,288 @@ include 'includes/header.php';
- + + + + + + + + \ No newline at end of file diff --git a/api/purchase_details.php b/api/purchase_details.php new file mode 100644 index 0000000..1e01031 --- /dev/null +++ b/api/purchase_details.php @@ -0,0 +1,31 @@ + false, 'error' => 'Missing ID']); + exit; +} + +$stmt = $pdo->prepare("SELECT * FROM purchases WHERE id = ?"); +$stmt->execute([$id]); +$purchase = $stmt->fetch(PDO::FETCH_ASSOC); + +if (!$purchase) { + echo json_encode(['success' => false, 'error' => 'Purchase not found']); + exit; +} + +$stmt = $pdo->prepare("SELECT pi.*, p.name as product_name FROM purchase_items pi JOIN products p ON pi.product_id = p.id WHERE pi.purchase_id = ?"); +$stmt->execute([$id]); +$items = $stmt->fetchAll(PDO::FETCH_ASSOC); + +echo json_encode([ + 'success' => true, + 'purchase' => $purchase, + 'items' => $items +]); diff --git a/assets/images/users/user_1_699d76ecd9c95.jpg b/assets/images/users/user_1_699d76ecd9c95.jpg new file mode 100644 index 0000000..9e8f8a2 Binary files /dev/null and b/assets/images/users/user_1_699d76ecd9c95.jpg differ diff --git a/includes/functions.php b/includes/functions.php index aef82bd..3933664 100644 --- a/includes/functions.php +++ b/includes/functions.php @@ -264,7 +264,7 @@ function get_logged_user() { function require_login() { if (!get_logged_user()) { - header('Location: /login.php'); + header('Location: ' . get_base_url() . 'login.php'); exit; } } diff --git a/login.php b/login.php index a66e114..e404608 100644 --- a/login.php +++ b/login.php @@ -4,9 +4,11 @@ require_once __DIR__ . '/includes/functions.php'; init_session(); +$baseUrl = get_base_url(); + // Redirect if already logged in if (get_logged_user()) { - header('Location: /admin/index.php'); + header('Location: ' . $baseUrl . 'admin/index.php'); exit; } @@ -17,7 +19,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') { $password = $_POST['password'] ?? ''; if (login_user($username, $password)) { - header('Location: /admin/index.php'); + header('Location: ' . $baseUrl . 'admin/index.php'); exit; } else { $error = 'Invalid username or password.'; @@ -34,7 +36,7 @@ $settings = get_company_settings(); Login - <?= htmlspecialchars($settings['company_name']) ?> - +