From 6e3e0c556acef128da91005e07c316ada90b8dad Mon Sep 17 00:00:00 2001
From: Flatlogic Bot
Date: Sun, 19 Apr 2026 10:09:23 +0000
Subject: [PATCH] Autosave: 20260419-100930
---
api/customers.php | 2 +-
api/settings.php | 2 +-
api/suppliers.php | 2 +-
categories.php | 2 +-
customers.php | 2 +-
edit_sale.php | 2 +-
includes/app.php | 1 +
includes/header.php | 18 ++-
pos.php | 2 +-
print_labels.php | 278 ++++++++++++++++++++++++++++++++++++++++++++
print_receipt.php | 2 +-
purchases.php | 2 +-
reports.php | 2 +-
sale.php | 2 +-
sales.php | 2 +-
stock.php | 51 +++++++-
suppliers.php | 2 +-
units.php | 2 +-
users.php | 91 ++++++++++++---
19 files changed, 427 insertions(+), 40 deletions(-)
create mode 100644 print_labels.php
diff --git a/api/customers.php b/api/customers.php
index f7682e1..c1255d2 100644
--- a/api/customers.php
+++ b/api/customers.php
@@ -1,6 +1,6 @@
["name_ar" => "نقاط البيع", "name_en" => "POS", "actions" => ["show", "add"]], "normal_sale" => ["name_ar" => "بيع عادي", "name_en" => "Normal Sale", "actions" => ["show", "add"]], "sales" => ["name_ar" => "المبيعات", "name_en" => "Sales", "actions" => ["show", "edit", "del"]], "purchases" => ["name_ar" => "المشتريات", "name_en" => "Purchases", "actions" => ["show", "add", "edit", "del"]], "stock" => ["name_ar" => "المخزون", "name_en" => "Stock", "actions" => ["show", "add", "edit", "del"]], "reports" => ["name_ar" => "التقارير", "name_en" => "Reports", "actions" => ["show"]], "customers" => ["name_ar" => "العملاء", "name_en" => "Customers", "actions" => ["show", "add", "edit", "del"]], "suppliers" => ["name_ar" => "الموردين", "name_en" => "Suppliers", "actions" => ["show", "add", "edit", "del"]], "categories" => ["name_ar" => "التصنيفات", "name_en" => "Categories", "actions" => ["show", "add", "edit", "del"]], "units" => ["name_ar" => "الوحدات", "name_en" => "Units", "actions" => ["show", "add", "edit", "del"]], "users" => ["name_ar" => "المستخدمين", "name_en" => "Users", "actions" => ["show", "add", "edit", "del"]], "settings" => ["name_ar" => "الإعدادات", "name_en" => "Settings", "actions" => ["show", "edit"]]]; } function has_permission(string $m, string $a = "show"): bool { $u = current_user(); if (!$u) return false; if ($u["role"] === "owner") return true; $p = !empty($u["permissions"]) ? (is_array($u["permissions"]) ? $u["permissions"] : json_decode($u["permissions"], true)) : []; return !empty($p[$m][$a]); } function require_permission(string $m, string $a = "show"): array { $u = require_auth(); if (!has_permission($m, $a)) { set_flash("warning", tr("ليس لديك صلاحية.", "You do not have permission.")); redirect_to("index.php"); } return $u; }
function require_roles(array $roles): array
{
$user = require_auth();
diff --git a/includes/header.php b/includes/header.php
index 86cb7ae..a860e12 100644
--- a/includes/header.php
+++ b/includes/header.php
@@ -71,7 +71,8 @@ $isPublic = !isset($user) || !$user;
= h(tr('لوحة التحكم', 'Dashboard')) ?>
-
+
+
= h(tr('المخزون', 'Inventory')) ?>
@@ -91,8 +92,10 @@ $isPublic = !isset($user) || !$user;
+
-
+
+
= h(tr('المبيعات', 'Sales')) ?>
@@ -112,8 +115,10 @@ $isPublic = !isset($user) || !$user;
+
-
+
+
= h(tr('المشتريات', 'Purchases')) ?>
@@ -129,24 +134,25 @@ $isPublic = !isset($user) || !$user;
+
= h(tr('الموردون', 'Suppliers')) ?>
= h(tr('العملاء', 'Customers')) ?>
-
+
= h(tr('التقارير', 'Reports')) ?>
-
+
= h(tr('المستخدمون والأدوار', 'Users & Roles')) ?>
-
+
= h(tr('إعدادات الشركة', 'Company Settings')) ?>
diff --git a/pos.php b/pos.php
index e0b2815..1a08240 100644
--- a/pos.php
+++ b/pos.php
@@ -1,7 +1,7 @@
prepare("SELECT * FROM items WHERE sku IN ($placeholders)");
+ $stmt->execute($skus);
+ $results = $stmt->fetchAll();
+ // Index by SKU
+ foreach ($results as $row) {
+ $items[$row['sku']] = $row;
+ }
+}
+
+// Templates configuration
+$templates = [
+ 'avery_65' => [
+ 'name' => 'Avery L7651 - 65 Labels (38.1 x 21.2 mm)',
+ 'cols' => 5,
+ 'rows' => 13,
+ 'width' => '38.1mm',
+ 'height' => '21.2mm',
+ 'margin_top' => '10.5mm',
+ 'margin_left' => '4.7mm',
+ 'gap_x' => '2.5mm',
+ 'gap_y' => '0mm',
+ ],
+ 'avery_54' => [
+ 'name' => 'Avery 54 Labels (32 x 25.4 mm)',
+ 'cols' => 6,
+ 'rows' => 9,
+ 'width' => '32mm',
+ 'height' => '25.4mm',
+ 'margin_top' => '10mm',
+ 'margin_left' => '5mm',
+ 'gap_x' => '2mm',
+ 'gap_y' => '0mm',
+ ],
+ 'avery_45' => [
+ 'name' => 'Avery 45 Labels (38.1 x 29.6 mm)',
+ 'cols' => 5,
+ 'rows' => 9,
+ 'width' => '38.1mm',
+ 'height' => '29.6mm',
+ 'margin_top' => '15mm',
+ 'margin_left' => '5mm',
+ 'gap_x' => '2mm',
+ 'gap_y' => '0mm',
+ ]
+];
+
+$templateId = $_REQUEST['template'] ?? 'avery_65';
+$tpl = $templates[$templateId] ?? $templates['avery_65'];
+
+// Prepare labels to print
+$labelsToPrint = [];
+if (!empty($items)) {
+ // Check if quantities are posted
+ if ($_SERVER['REQUEST_METHOD'] === 'POST' && !empty($_POST['qty'])) {
+ foreach ($_POST['qty'] as $sku => $qty) {
+ if (isset($items[$sku])) {
+ for ($i = 0; $i < (int)$qty; $i++) {
+ $labelsToPrint[] = $items[$sku];
+ }
+ }
+ }
+ } else {
+ // Default 1 per item
+ foreach ($skus as $sku) {
+ if (isset($items[$sku])) {
+ $labelsToPrint[] = $items[$sku];
+ }
+ }
+ }
+}
+
+?>
+
+
+
+
+ = h(tr('طباعة ملصقات', 'Print Labels')) ?>
+
+
+
+
+
+
+
+
+
+
+
= h(tr('معاينة الطباعة', 'Print Preview')) ?>
+ $pageLabels):
+ ?>
+
+
+
+
= h($label['name']) ?>
+
+
+
+
= h($label['sku']) ?>
+
= h(currency($label['price'])) ?>
+
+
+
+
+
+
+
+
+
+
diff --git a/print_receipt.php b/print_receipt.php
index acd5442..5bc9c1b 100644
--- a/print_receipt.php
+++ b/print_receipt.php
@@ -1,6 +1,6 @@
= h(tr('إدارة الأصناف وجرد المخزون.', 'Manage items and inventory.')) ?>
+
@@ -198,6 +201,9 @@ require __DIR__ . '/includes/header.php';
+ |
+
+ |
SKU |
= h(tr('صورة', 'Pic')) ?> |
= h(tr('الصنف', 'Product')) ?> |
@@ -212,11 +218,14 @@ require __DIR__ . '/includes/header.php';
- | = h(tr('لا توجد بيانات', 'No data found')) ?> |
+ | = h(tr('لا توجد بيانات', 'No data found')) ?> |
- | = h($row['sku']) ?> |
+
+
+ |
+ = h($row['sku']) ?> |
@@ -243,6 +252,9 @@ require __DIR__ . '/includes/header.php';
+
+
+
@@ -533,6 +545,37 @@ function deleteItem(sku) {
}
});
}
+
+function toggleAllCheckboxes(source) {
+ const checkboxes = document.querySelectorAll(".item-checkbox");
+ for (let i = 0; i < checkboxes.length; i++) {
+ checkboxes[i].checked = source.checked;
+ }
+}
+
+function printBulkLabels() {
+ const checkboxes = document.querySelectorAll(".item-checkbox:checked");
+ if (checkboxes.length === 0) {
+ Swal.fire('= h(tr("تنبيه", "Warning")) ?>', '= h(tr("يرجى تحديد صنف واحد على الأقل", "Please select at least one item")) ?>', 'warninginaly);
+ return;
+ }
+
+ let skus = [];
+ checkboxes.forEach((cb) => skus.push(cb.value));
+
+ const form = document.createElement('form');
+ form.method = 'POST';
+ form.action = 'print_labels.php';
+
+ const input = document.createElement('input');
+ input.type = 'hidden';
+ input.name = 'skus';
+ input.value = skus.join(\",\");
+
+ form.appendChild(input);
+ document.body.appendChild(form);
+ form.submit();
+}
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/suppliers.php b/suppliers.php
index b6cd5e5..6da55f0 100644
--- a/suppliers.php
+++ b/suppliers.php
@@ -1,6 +1,6 @@
prepare("INSERT INTO users (username, password, role, branch_code, name_ar, name_en) VALUES (?, ?, ?, ?, ?, ?)");
- $stmt->execute([$username, $hash, $role, $branch_code, $name_ar, $name_en]);
+ $stmt = db()->prepare("INSERT INTO users (username, password, role, branch_code, name_ar, name_en, permissions) VALUES (?, ?, ?, ?, ?, ?, ?)");
+ $perms = isset($_POST["permissions"]) ? json_encode($_POST["permissions"]) : "{}";
+ $stmt->execute([$username, $hash, $role, $branch_code, $name_ar, $name_en, $perms]);
set_flash('success', tr('تمت إضافة المستخدم بنجاح.', 'User added successfully.'));
} catch (PDOException $e) {
set_flash('error', tr('حدث خطأ، قد يكون اسم المستخدم موجوداً مسبقاً.', 'Error occurred, username might already exist.'));
@@ -34,6 +36,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($action === 'edit') {
+ if (!has_permission('users', 'edit')) { set_flash('error', tr('ليس لديك صلاحية', 'No permission')); redirect_to('users.php'); }
$id = (int)($_POST['id'] ?? 0);
$username = trim($_POST['username'] ?? '');
$name_ar = trim($_POST['name_ar'] ?? '');
@@ -46,11 +49,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
try {
if ($password) {
$hash = password_hash($password, PASSWORD_DEFAULT);
- $stmt = db()->prepare("UPDATE users SET username=?, password=?, role=?, branch_code=?, name_ar=?, name_en=? WHERE id=?");
- $stmt->execute([$username, $hash, $role, $branch_code, $name_ar, $name_en, $id]);
+ $stmt = db()->prepare("UPDATE users SET username=?, password=?, role=?, branch_code=?, name_ar=?, name_en=?, permissions=? WHERE id=?");
+ $perms = isset($_POST["permissions"]) ? json_encode($_POST["permissions"]) : "{}";
+ $stmt->execute([$username, $hash, $role, $branch_code, $name_ar, $name_en, $perms, $id]);
} else {
- $stmt = db()->prepare("UPDATE users SET username=?, role=?, branch_code=?, name_ar=?, name_en=? WHERE id=?");
- $stmt->execute([$username, $role, $branch_code, $name_ar, $name_en, $id]);
+ $stmt = db()->prepare("UPDATE users SET username=?, role=?, branch_code=?, name_ar=?, name_en=?, permissions=? WHERE id=?");
+ $perms = isset($_POST["permissions"]) ? json_encode($_POST["permissions"]) : "{}";
+ $stmt->execute([$username, $role, $branch_code, $name_ar, $name_en, $perms, $id]);
}
set_flash('success', tr('تم تعديل المستخدم بنجاح.', 'User updated successfully.'));
} catch (PDOException $e) {
@@ -61,6 +66,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
}
if ($action === 'delete') {
+ if (!has_permission('users', 'del')) { set_flash('error', tr('ليس لديك صلاحية', 'No permission')); redirect_to('users.php'); }
$id = (int)($_POST['id'] ?? 0);
if ($id && $id !== $user['id']) {
$stmt = db()->prepare("DELETE FROM users WHERE id=?");
@@ -103,9 +109,11 @@ require __DIR__ . '/includes/header.php';
= h(tr('الوصول حسب الدور', 'Role-based access')) ?>
= h(tr('إدارة المستخدمين وصلاحيات الوصول للنظام.', 'Manage users and system access permissions.')) ?>
+
+
|
@@ -149,15 +155,13 @@ require __DIR__ . '/includes/header.php';
= h(role_label($account['role'])) ?> |
= h(branch_label($account['branch_code'])) ?> |
- = h(tr('نعم', 'Yes')) ?> |
- = h(in_array($account['role'], ['owner', 'manager'], true) ? tr('نعم', 'Yes') : tr('لا', 'No')) ?> |
- = h($account['role'] === 'owner' ? tr('نعم', 'Yes') : tr('لا', 'No')) ?> |
+ = h(empty($account["permissions"]) || $account["permissions"] === "{}" ? tr("الافتراضي", "Default") : tr("مخصصة", "Custom")) ?> |
-
+
|