@@ -253,11 +276,14 @@ include 'includes/header.php';
ID
Outlet
+ Cashier
Customer
Type
Source
- Items
Total
+
+ Commission
+
Payment
Status
Time
@@ -274,6 +300,9 @@ include 'includes/header.php';
= htmlspecialchars($order['outlet_name'] ?? 'Unknown') ?>
+
+ @= htmlspecialchars((string)($order['cashier_name'] ?? 'Guest')) ?>
+
= htmlspecialchars((string)($order['customer_name'] ?? '')) ?>
@@ -303,8 +332,12 @@ include 'includes/header.php';
= ucfirst($order['order_type']) ?>
- = htmlspecialchars((string)($order['items_summary'] ?? '')) ?>
- = format_currency($order['total_amount']) ?>
+ = format_currency($order['total_amount']) ?>
+
+
+ = format_currency($order['commission_amount']) ?>
+
+
-
+
No active orders found matching your criteria.
diff --git a/admin/users.php b/admin/users.php
index a48d9de..5658438 100644
--- a/admin/users.php
+++ b/admin/users.php
@@ -16,6 +16,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$group_id = (int)$_POST['group_id'];
$is_active = isset($_POST['is_active']) ? 1 : 0;
$is_ratable = isset($_POST['is_ratable']) ? 1 : 0;
+ $commission_rate = (float)($_POST['commission_rate'] ?? 0);
$id = isset($_POST['id']) ? (int)$_POST['id'] : null;
$profile_pic = null;
@@ -46,13 +47,13 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
if (!has_permission('users_edit') && !has_permission('users_add')) {
$message = 'Access Denied: You do not have permission to edit users.
';
} else {
- $sql = "UPDATE users SET username = ?, full_name = ?, full_name_ar = ?, email = ?, group_id = ?, is_active = ?, is_ratable = ?, profile_pic = ? WHERE id = ?";
- $params = [$username, $full_name, $full_name_ar, $email, $group_id, $is_active, $is_ratable, $profile_pic, $id];
+ $sql = "UPDATE users SET username = ?, full_name = ?, full_name_ar = ?, email = ?, group_id = ?, is_active = ?, is_ratable = ?, profile_pic = ?, commission_rate = ? WHERE id = ?";
+ $params = [$username, $full_name, $full_name_ar, $email, $group_id, $is_active, $is_ratable, $profile_pic, $commission_rate, $id];
if (!empty($_POST['password'])) {
$password = password_hash($_POST['password'], PASSWORD_DEFAULT);
- $sql = "UPDATE users SET username = ?, full_name = ?, full_name_ar = ?, email = ?, group_id = ?, is_active = ?, is_ratable = ?, profile_pic = ?, password = ? WHERE id = ?";
- $params = [$username, $full_name, $full_name_ar, $email, $group_id, $is_active, $is_ratable, $profile_pic, $password, $id];
+ $sql = "UPDATE users SET username = ?, full_name = ?, full_name_ar = ?, email = ?, group_id = ?, is_active = ?, is_ratable = ?, profile_pic = ?, commission_rate = ?, password = ? WHERE id = ?";
+ $params = [$username, $full_name, $full_name_ar, $email, $group_id, $is_active, $is_ratable, $profile_pic, $commission_rate, $password, $id];
}
$stmt = $pdo->prepare($sql);
@@ -64,8 +65,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['action'])) {
$message = 'Access Denied: You do not have permission to add users.
';
} else {
$password = password_hash($_POST['password'] ?: '123456', PASSWORD_DEFAULT);
- $stmt = $pdo->prepare("INSERT INTO users (username, password, full_name, full_name_ar, email, group_id, is_active, is_ratable, profile_pic) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
- $stmt->execute([$username, $password, $full_name, $full_name_ar, $email, $group_id, $is_active, $is_ratable, $profile_pic]);
+ $stmt = $pdo->prepare("INSERT INTO users (username, password, full_name, full_name_ar, email, group_id, is_active, is_ratable, profile_pic, commission_rate) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
+ $stmt->execute([$username, $password, $full_name, $full_name_ar, $email, $group_id, $is_active, $is_ratable, $profile_pic, $commission_rate]);
$message = 'User created successfully!
';
}
}
@@ -137,7 +138,7 @@ include 'includes/header.php';
Email
Role / Group
Status
- Ratable
+ Commission
Actions
@@ -168,11 +169,7 @@ include 'includes/header.php';
-
- Yes
-
- No
-
+ = number_format($user['commission_rate'], 1) ?>%
@@ -261,6 +258,16 @@ include 'includes/header.php';
+
+
+
COMMISSION RATE (%)
+
+
+ %
+
+
Percentage earned per sale processed by this user.
+
+
PROFILE PICTURE
@@ -299,6 +306,7 @@ function prepareAddForm() {
document.getElementById('pwdHint').style.display = 'none';
document.getElementById('userPassword').required = true;
document.getElementById('userImagePreviewContainer').style.display = 'none';
+ document.getElementById('userCommissionRate').value = '0.0';
}
function prepareEditForm(user) {
@@ -313,6 +321,7 @@ function prepareEditForm(user) {
document.getElementById('userGroupId').value = user.group_id || '';
document.getElementById('userIsActive').checked = user.is_active == 1;
document.getElementById('userIsRatable').checked = user.is_ratable == 1;
+ document.getElementById('userCommissionRate').value = user.commission_rate || '0.0';
document.getElementById('userPassword').required = false;
document.getElementById('pwdLabel').style.display = 'none';
document.getElementById('pwdHint').style.display = 'block';
diff --git a/api/order.php b/api/order.php
index feb56b4..bbcc8dd 100644
--- a/api/order.php
+++ b/api/order.php
@@ -72,10 +72,10 @@ try {
// Fetch Loyalty Settings
$settingsStmt = $pdo->query("SELECT is_enabled, points_per_order, points_for_free_meal FROM loyalty_settings WHERE id = 1");
- $settings = $settingsStmt->fetch(PDO::FETCH_ASSOC);
- $loyalty_enabled = $settings ? (bool)$settings['is_enabled'] : true;
- $points_per_order = $settings ? intval($settings['points_per_order']) : 10;
- $points_threshold = $settings ? intval($settings['points_for_free_meal']) : 70;
+ $loyaltySettings = $settingsStmt->fetch(PDO::FETCH_ASSOC);
+ $loyalty_enabled = $loyaltySettings ? (bool)$loyaltySettings['is_enabled'] : true;
+ $points_per_order = $loyaltySettings ? intval($loyaltySettings['points_per_order']) : 10;
+ $points_threshold = $loyaltySettings ? intval($loyaltySettings['points_for_free_meal']) : 70;
$current_points = 0;
$points_deducted = 0;
@@ -189,6 +189,19 @@ try {
$final_total = max(0, $calculated_total + $vat);
+ // Commission Calculation
+ $commission_amount = 0;
+ $companySettings = get_company_settings();
+ if (!empty($companySettings['commission_enabled']) && $user_id) {
+ $userStmt = $pdo->prepare("SELECT commission_rate FROM users WHERE id = ?");
+ $userStmt->execute([$user_id]);
+ $commission_rate = (float)$userStmt->fetchColumn();
+ if ($commission_rate > 0) {
+ // Commission is usually calculated on the subtotal (before tax/VAT)
+ $commission_amount = $calculated_total * ($commission_rate / 100);
+ }
+ }
+
// Check for Existing Order ID (Update Mode)
$order_id = isset($data['order_id']) ? intval($data['order_id']) : null;
$is_update = false;
@@ -208,21 +221,22 @@ try {
$stmt = $pdo->prepare("UPDATE orders SET
outlet_id = ?, table_id = ?, table_number = ?, order_type = ?,
customer_id = ?, customer_name = ?, customer_phone = ?,
- payment_type_id = ?, total_amount = ?, discount = ?, user_id = ?, status = 'pending'
+ payment_type_id = ?, total_amount = ?, discount = ?, user_id = ?,
+ commission_amount = ?, status = 'pending'
WHERE id = ?");
$stmt->execute([
$outlet_id, $table_id, $table_number, $order_type,
$customer_id, $customer_name, $customer_phone,
$payment_type_id, $final_total, $vat, $user_id,
- $order_id
+ $commission_amount, $order_id
]);
$delStmt = $pdo->prepare("DELETE FROM order_items WHERE order_id = ?");
$delStmt->execute([$order_id]);
} else {
// INSERT New Order
- $stmt = $pdo->prepare("INSERT INTO orders (outlet_id, table_id, table_number, order_type, customer_id, customer_name, customer_phone, payment_type_id, total_amount, discount, user_id, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending')");
- $stmt->execute([$outlet_id, $table_id, $table_number, $order_type, $customer_id, $customer_name, $customer_phone, $payment_type_id, $final_total, $vat, $user_id]);
+ $stmt = $pdo->prepare("INSERT INTO orders (outlet_id, table_id, table_number, order_type, customer_id, customer_name, customer_phone, payment_type_id, total_amount, discount, user_id, commission_amount, status) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, 'pending')");
+ $stmt->execute([$outlet_id, $table_id, $table_number, $order_type, $customer_id, $customer_name, $customer_phone, $payment_type_id, $final_total, $vat, $user_id, $commission_amount]);
$order_id = $pdo->lastInsertId();
}
@@ -321,4 +335,4 @@ You've earned *{points_earned} points* with this order.
if ($pdo->inTransaction()) $pdo->rollBack();
error_log("Order Error: " . $e->getMessage());
echo json_encode(['success' => false, 'error' => $e->getMessage()]);
-}
+}
\ No newline at end of file
diff --git a/db/migrations/034_commission_system.sql b/db/migrations/034_commission_system.sql
new file mode 100644
index 0000000..98daa44
--- /dev/null
+++ b/db/migrations/034_commission_system.sql
@@ -0,0 +1,8 @@
+-- Add commission toggle to company_settings
+ALTER TABLE company_settings ADD COLUMN commission_enabled TINYINT(1) DEFAULT 0;
+
+-- Add commission_rate to users
+ALTER TABLE users ADD COLUMN commission_rate DECIMAL(5, 2) DEFAULT 0.00;
+
+-- Add commission_amount to orders
+ALTER TABLE orders ADD COLUMN commission_amount DECIMAL(10, 2) DEFAULT 0.00;
diff --git a/includes/functions.php b/includes/functions.php
index 3933664..074f1f8 100644
--- a/includes/functions.php
+++ b/includes/functions.php
@@ -296,16 +296,39 @@ function require_permission($permission) {
* @return string The base URL.
*/
function get_base_url() {
- $protocol = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off' || $_SERVER['SERVER_PORT'] == 443) ? "https://" : "http://";
+ $protocol = 'http://';
+ if ((!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] !== 'off') ||
+ $_SERVER['SERVER_PORT'] == 443 ||
+ (isset($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] === 'https')) {
+ $protocol = 'https://';
+ }
+
$domainName = $_SERVER['HTTP_HOST'];
- // Remove admin/ if we are in it
+
+ // Calculate script directory
$script_dir = dirname($_SERVER['SCRIPT_NAME']);
- $script_dir = str_replace(['/admin', '/api'], '', $script_dir);
- if ($script_dir === '/') $script_dir = '';
+ // Replace only at the end to be safer
+ if (str_ends_with($script_dir, '/admin')) {
+ $script_dir = substr($script_dir, 0, -6);
+ } elseif (str_ends_with($script_dir, '/api')) {
+ $script_dir = substr($script_dir, 0, -4);
+ }
+
+ if ($script_dir === DIRECTORY_SEPARATOR || $script_dir === '/') {
+ $script_dir = '';
+ }
return $protocol . $domainName . $script_dir . '/';
}
+if (!function_exists('str_ends_with')) {
+ function str_ends_with($haystack, $needle) {
+ $length = strlen($needle);
+ if (!$length) return true;
+ return substr($haystack, -$length) === $needle;
+ }
+}
+
/**
* Backup functions
*/
diff --git a/login.php b/login.php
index e404608..6cb50d4 100644
--- a/login.php
+++ b/login.php
@@ -6,9 +6,25 @@ init_session();
$baseUrl = get_base_url();
+/**
+ * Determine where to redirect the user based on permissions
+ */
+function get_redirect_url($baseUrl) {
+ if (has_permission('dashboard_view')) {
+ return $baseUrl . 'admin/index.php';
+ } elseif (has_permission('pos')) {
+ return $baseUrl . 'pos.php';
+ } elseif (has_permission('kitchen_view')) {
+ return $baseUrl . 'kitchen.php';
+ }
+ // Fallback to admin index if no specific view permission found,
+ // the page itself will handle the final access denied
+ return $baseUrl . 'admin/index.php';
+}
+
// Redirect if already logged in
if (get_logged_user()) {
- header('Location: ' . $baseUrl . 'admin/index.php');
+ header('Location: ' . get_redirect_url($baseUrl));
exit;
}
@@ -19,7 +35,7 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$password = $_POST['password'] ?? '';
if (login_user($username, $password)) {
- header('Location: ' . $baseUrl . 'admin/index.php');
+ header('Location: ' . get_redirect_url($baseUrl));
exit;
} else {
$error = 'Invalid username or password.';
diff --git a/test_url.php b/test_url.php
deleted file mode 100644
index 70d733a..0000000
--- a/test_url.php
+++ /dev/null
@@ -1,7 +0,0 @@
-