From 1554df04a22114d93de64a7551c7f2510dfb1d56 Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Sun, 3 May 2026 06:58:37 +0000 Subject: [PATCH] Autosave: 20260503-065836 --- accounting.php | 5 + activate.php | 5 + backups.php | 5 + cash_registers.php | 5 + cashflow_report.php | 5 + categories.php | 5 + copy_outlet_data.php | 5 + customer_display_settings.php | 5 + customer_statement.php | 5 + customers.php | 5 + dashboard.php | 5 + devices.php | 5 + expense_categories.php | 5 + expense_report.php | 5 + expenses.php | 5 + expiry_report.php | 5 + hr_attendance.php | 5 + hr_departments.php | 5 + hr_employees.php | 5 + hr_payroll.php | 5 + includes/page_routes.php | 194 +++++ index.php | 986 ++++---------------------- items.php | 5 + logs.php | 5 + low_stock_report.php | 5 + loyalty_history.php | 5 + lpos.php | 5 + my_profile.php | 5 + outlets.php | 5 + page_bootstrap.php | 22 + pages/accounting_view.php | 2 +- pages/copy_outlet_data_view.php | 2 +- pages/role_groups_view.php | 173 +++++ pages/sales_purchases_handlers.php | 138 ++++ pages/sales_purchases_page_script.php | 6 + pages/sales_purchases_print_view.php | 2 +- pages/sales_purchases_save_logic.php | 4 +- pages/sales_purchases_view.php | 5 +- pages/settings_save_logic.php | 157 ++++ pages/settings_view.php | 666 +++++++++++++++++ payment_methods.php | 5 + pos.php | 5 + purchase_returns.php | 5 + purchases.php | 5 + quotations.php | 5 + register_sessions.php | 5 + role_groups.php | 5 + sales.php | 5 + sales_returns.php | 5 + scale_devices.php | 5 + session_cookie.txt | 5 + settings.php | 5 + supplier_statement.php | 5 + suppliers.php | 5 + units.php | 5 + users.php | 5 + 56 files changed, 1700 insertions(+), 872 deletions(-) create mode 100644 accounting.php create mode 100644 activate.php create mode 100644 backups.php create mode 100644 cash_registers.php create mode 100644 cashflow_report.php create mode 100644 categories.php create mode 100644 copy_outlet_data.php create mode 100644 customer_display_settings.php create mode 100644 customer_statement.php create mode 100644 customers.php create mode 100644 dashboard.php create mode 100644 devices.php create mode 100644 expense_categories.php create mode 100644 expense_report.php create mode 100644 expenses.php create mode 100644 expiry_report.php create mode 100644 hr_attendance.php create mode 100644 hr_departments.php create mode 100644 hr_employees.php create mode 100644 hr_payroll.php create mode 100644 includes/page_routes.php create mode 100644 items.php create mode 100644 logs.php create mode 100644 low_stock_report.php create mode 100644 loyalty_history.php create mode 100644 lpos.php create mode 100644 my_profile.php create mode 100644 outlets.php create mode 100644 page_bootstrap.php create mode 100644 pages/role_groups_view.php create mode 100644 pages/sales_purchases_handlers.php create mode 100644 pages/sales_purchases_page_script.php create mode 100644 pages/settings_save_logic.php create mode 100644 pages/settings_view.php create mode 100644 payment_methods.php create mode 100644 pos.php create mode 100644 purchase_returns.php create mode 100644 purchases.php create mode 100644 quotations.php create mode 100644 register_sessions.php create mode 100644 role_groups.php create mode 100644 sales.php create mode 100644 sales_returns.php create mode 100644 scale_devices.php create mode 100644 session_cookie.txt create mode 100644 settings.php create mode 100644 supplier_statement.php create mode 100644 suppliers.php create mode 100644 units.php create mode 100644 users.php diff --git a/accounting.php b/accounting.php new file mode 100644 index 0000000..bdd9363 --- /dev/null +++ b/accounting.php @@ -0,0 +1,5 @@ + 'activate.php', + 'dashboard' => 'dashboard.php', + 'pos' => 'pos.php', + 'sales' => 'sales.php', + 'sales_returns' => 'sales_returns.php', + 'purchases' => 'purchases.php', + 'purchase_returns' => 'purchase_returns.php', + 'quotations' => 'quotations.php', + 'lpos' => 'lpos.php', + 'accounting' => 'accounting.php', + 'expense_categories' => 'expense_categories.php', + 'expenses' => 'expenses.php', + 'expense_report' => 'expense_report.php', + 'items' => 'items.php', + 'categories' => 'categories.php', + 'units' => 'units.php', + 'customers' => 'customers.php', + 'suppliers' => 'suppliers.php', + 'customer_statement' => 'customer_statement.php', + 'supplier_statement' => 'supplier_statement.php', + 'cashflow_report' => 'cashflow_report.php', + 'expiry_report' => 'expiry_report.php', + 'low_stock_report' => 'low_stock_report.php', + 'loyalty_history' => 'loyalty_history.php', + 'payment_methods' => 'payment_methods.php', + 'settings' => 'settings.php', + 'devices' => 'devices.php', + 'hr_departments' => 'hr_departments.php', + 'hr_employees' => 'hr_employees.php', + 'hr_attendance' => 'hr_attendance.php', + 'hr_payroll' => 'hr_payroll.php', + 'role_groups' => 'role_groups.php', + 'users' => 'users.php', + 'scale_devices' => 'scale_devices.php', + 'customer_display_settings' => 'customer_display_settings.php', + 'backups' => 'backups.php', + 'logs' => 'logs.php', + 'cash_registers' => 'cash_registers.php', + 'register_sessions' => 'register_sessions.php', + 'outlets' => 'outlets.php', + 'my_profile' => 'my_profile.php', + 'copy_outlet_data' => 'copy_outlet_data.php', + ]; + + return $map; + } +} + +if (!function_exists('page_entry_script')) { + function page_entry_script(string $page): ?string { + $page = strtolower(trim($page)); + if ($page === '') { + return null; + } + + $map = page_entrypoint_map(); + return $map[$page] ?? null; + } +} + +if (!function_exists('page_from_entry_script')) { + function page_from_entry_script(?string $scriptName = null): ?string { + static $reverse = null; + if ($reverse === null) { + $reverse = array_flip(page_entrypoint_map()); + } + + $scriptName = strtolower(trim((string)($scriptName ?? basename((string)($_SERVER['SCRIPT_NAME'] ?? ''))))); + if ($scriptName === '') { + return null; + } + + return $reverse[$scriptName] ?? null; + } +} + +if (!function_exists('page_url')) { + function page_url(string $page = 'dashboard', array $params = []): string { + $targetScript = page_entry_script($page); + $query = $params; + + if ($targetScript === null) { + $targetScript = 'index.php'; + if ($page !== '' && strtolower($page) !== 'dashboard') { + $query = ['page' => $page] + $query; + } + } + + $queryString = http_build_query($query); + return $targetScript . ($queryString !== '' ? '?' . $queryString : ''); + } +} + +if (!function_exists('page_normalize_url')) { + function page_normalize_url(string $url): string { + $url = trim($url); + if ($url === '') { + return $url; + } + + $parts = parse_url($url); + if ($parts === false) { + return $url; + } + + $query = []; + if (!empty($parts['query'])) { + parse_str($parts['query'], $query); + } + + $page = isset($query['page']) ? strtolower(trim((string)$query['page'])) : ''; + if ($page === '') { + return $url; + } + + $targetScript = page_entry_script($page); + if ($targetScript === null) { + return $url; + } + + $path = (string)($parts['path'] ?? ''); + $basename = strtolower(trim($path !== '' ? basename($path) : '')); + $knownRoutePage = $basename !== '' ? page_from_entry_script($basename) : null; + + if ($path !== '' && str_starts_with($path, '/')) { + $targetPath = '/' . $targetScript; + } else { + $targetPath = $targetScript; + } + + if ($basename === '' || $basename === 'index.php' || $knownRoutePage !== null) { + $parts['path'] = $targetPath; + unset($query['page']); + } else { + return $url; + } + + $normalized = (string)($parts['path'] ?? $targetPath); + if (!empty($query)) { + $normalized .= '?' . http_build_query($query); + } + if (isset($parts['fragment']) && $parts['fragment'] !== '') { + $normalized .= '#' . $parts['fragment']; + } + + return $normalized; + } +} + +if (!function_exists('page_request_is_ajax')) { + function page_request_is_ajax(): bool { + return strtolower((string)($_SERVER['HTTP_X_REQUESTED_WITH'] ?? '')) === 'xmlhttprequest'; + } +} + +if (!function_exists('page_redirect_legacy_url')) { + function page_redirect_legacy_url(): void { + if (PHP_SAPI === 'cli') { + return; + } + + if (strtoupper((string)($_SERVER['REQUEST_METHOD'] ?? 'GET')) !== 'GET') { + return; + } + + if (!isset($_GET['page']) || page_request_is_ajax()) { + return; + } + + $requestUri = (string)($_SERVER['REQUEST_URI'] ?? ''); + if ($requestUri === '') { + return; + } + + $normalized = page_normalize_url($requestUri); + if ($normalized !== '' && $normalized !== $requestUri) { + header('Location: ' . $normalized, true, 302); + exit; + } + } +} + +if (!function_exists('set_route_page_context')) { + function set_route_page_context(string $page): void { + $_GET['page'] = $page; + $_REQUEST['page'] = $page; + } +} diff --git a/index.php b/index.php index 1a616b1..080637c 100644 --- a/index.php +++ b/index.php @@ -36,6 +36,11 @@ if ((isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on') || (isset($_SERVER[ session_start(); +require_once __DIR__ . '/includes/page_routes.php'; +if (!defined('APP_ROUTE_BOOTSTRAP')) { + page_redirect_legacy_url(); +} + if (!function_exists('app_file_debug_logging_enabled')) { function app_file_debug_logging_enabled(): bool { static $enabled = null; @@ -621,7 +626,7 @@ try { $page = $_GET['page'] ?? 'dashboard'; if (!$can_access && $page !== 'activate') { - header("Location: index.php?page=activate"); + header("Location: " . page_url("activate")); exit; } @@ -674,8 +679,8 @@ if ($page === 'activate') { @@ -1882,8 +1887,9 @@ function validateItemSkuBarcode(string $sku): ?string { function redirectWithMessage($msg, $url = null) { if (!$url) { - $url = $_SERVER['REQUEST_URI']; + $url = $_SERVER['REQUEST_URI'] ?? 'dashboard.php'; } + $url = page_normalize_url((string)$url); $_SESSION['message'] = $msg; header("Location: $url"); exit; @@ -2376,112 +2382,8 @@ function getPromotionalPrice($item) { redirectWithMessage("LPO deleted!", "index.php?page=lpos"); } - if (isset($_POST['convert_to_invoice'])) { - $db = db(); - try { - $db->beginTransaction(); - $quot_id = (int)$_POST['quotation_id']; - - $stmt = $db->prepare("SELECT * FROM quotations WHERE id = ?"); - $stmt->execute([$quot_id]); - $quot = $stmt->fetch(); - - if (!$quot) throw new Exception("Quotation not found."); - if ($quot['status'] === 'converted') throw new Exception("Quotation already converted."); - - $stmtItems = $db->prepare("SELECT * FROM quotation_items WHERE quotation_id = ?"); - $stmtItems->execute([$quot_id]); - $qItems = $stmtItems->fetchAll(); - - // Create Invoice - $inv_date = date('Y-m-d'); - $stmtInv = $db->prepare("INSERT INTO invoices (customer_id, invoice_date, status, payment_type, total_amount, vat_amount, total_with_vat, paid_amount, outlet_id) VALUES (?, ?, 'unpaid', 'credit', ?, ?, ?, 0, ?)"); - $stmtInv->execute([$quot['customer_id'], $inv_date, $quot['total_amount'], $quot['vat_amount'], $quot['total_with_vat'], current_outlet_id()]); - $inv_id = $db->lastInsertId(); - - $items_for_journal = []; - foreach ($qItems as $item) { - $lineVatAmount = line_item_vat_amount($db, $item); - $db->prepare("INSERT INTO invoice_items (invoice_id, item_id, quantity, unit_price, vat_amount, total_price) VALUES (?, ?, ?, ?, ?, ?)")->execute([$inv_id, $item['item_id'], $item['quantity'], $item['unit_price'], $lineVatAmount, $item['total_price']]); - - // Update stock - update_stock($item['item_id'], -$item['quantity']); - $items_for_journal[] = ['id' => $item['item_id'], 'qty' => $item['quantity']]; - } - - // Update Quotation status - $db->prepare("UPDATE quotations SET status = 'converted' WHERE id = ?")->execute([$quot_id]); - - // Accounting - recordSaleJournal($inv_id, $quot['total_with_vat'], $inv_date, $items_for_journal, $quot['vat_amount']); - - $db->commit(); - redirectWithMessage("Quotation converted to Invoice #$inv_id successfully!", "index.php?page=sales"); - } catch (Exception $e) { $db->rollBack(); $message = "Error: " . $e->getMessage(); } - } - - if (isset($_POST['convert_lpo_to_purchase'])) { - $db = db(); - try { - $db->beginTransaction(); - $lpo_id = (int)$_POST['lpo_id']; - - $stmt = $db->prepare("SELECT * FROM lpos WHERE id = ?"); - $stmt->execute([$lpo_id]); - $lpo = $stmt->fetch(); - - if (!$lpo) throw new Exception("LPO not found."); - if ($lpo['status'] === 'converted') throw new Exception("LPO already converted."); - - $stmtItems = $db->prepare("SELECT * FROM lpo_items WHERE lpo_id = ?"); - $stmtItems->execute([$lpo_id]); - $lItems = $stmtItems->fetchAll(); - - // Create Purchase Invoice - $pur_date = date('Y-m-d'); - $stmtPur = $db->prepare("INSERT INTO purchases (supplier_id, invoice_date, status, payment_type, total_amount, vat_amount, total_with_vat, paid_amount, outlet_id) VALUES (?, ?, 'unpaid', 'credit', ?, ?, ?, 0, ?)"); - $stmtPur->execute([$lpo['supplier_id'], $pur_date, $lpo['total_amount'], $lpo['vat_amount'], $lpo['total_with_vat'], current_outlet_id()]); - $pur_id = $db->lastInsertId(); - - $items_for_journal = []; - foreach ($lItems as $item) { - $db->prepare("INSERT INTO purchase_items (purchase_id, item_id, quantity, unit_price, vat_amount, total_price) VALUES (?, ?, ?, ?, ?, ?)")->execute([$pur_id, $item['item_id'], $item['quantity'], $item['unit_price'], $item['vat_amount'], $item['total_amount']]); - - // Update stock - update_stock($item['item_id'], $item['quantity']); - $items_for_journal[] = ['id' => $item['item_id'], 'qty' => $item['quantity']]; - } - - // Update LPO status - $db->prepare("UPDATE lpos SET status = 'converted' WHERE id = ?")->execute([$lpo_id]); - - $db->commit(); - redirectWithMessage("LPO converted to Purchase Invoice #$pur_id successfully!", "index.php?page=purchases"); - } catch (Exception $e) { $db->rollBack(); $message = "Error: " . $e->getMessage(); } - } - - if (isset($_POST['record_payment'])) { - $id = (int)$_POST['invoice_id']; - $amount = (float)$_POST['amount']; - $date = $_POST['payment_date'] ?: date('Y-m-d'); - $method = $_POST['payment_method'] ?? 'Cash'; - $type = ($page === 'purchases') ? 'purchase' : 'sale'; - $table = ($type === 'purchase') ? 'purchases' : 'invoices'; - $payment_table = ($type === 'purchase') ? 'purchase_payments' : 'payments'; - $fk_col = ($type === 'purchase') ? 'purchase_id' : 'invoice_id'; - - $db = db(); - $db->prepare("INSERT INTO $payment_table ($fk_col, amount, payment_date, payment_method, notes) VALUES (?, ?, ?, ?, ?)")->execute([$id, $amount, $date, $method, $_POST['notes'] ?? '']); - $pay_id = $db->lastInsertId(); - $db->prepare("UPDATE $table SET paid_amount = paid_amount + ?, status = IF(paid_amount + ? >= total_with_vat, 'paid', 'partially_paid') WHERE id = ?")->execute([$amount, $amount, $id]); - - if ($type === 'sale') recordPaymentReceivedJournal((int)$pay_id, $amount, $date, $method); - else recordPaymentMadeJournal((int)$pay_id, $amount, $date, $method); - - $_SESSION['trigger_receipt_modal'] = true; - $_SESSION['show_receipt_id'] = $pay_id; - redirectWithMessage("Payment recorded!", "index.php?page=" . ($type === 'purchase' ? 'purchases' : 'sales')); - } + // Sales/Purchases secondary handlers + require_once __DIR__ . '/pages/sales_purchases_handlers.php'; if (isset($_POST['add_expense'])) { $amt = (float)$_POST['amount']; @@ -2773,18 +2675,6 @@ function getPromotionalPrice($item) { redirectWithMessage("Payment method deleted!", "index.php?page=payment_methods"); } - if (isset($_POST['delete_invoice'])) { - $id = (int)$_POST['id']; - $type = ($page === 'purchases') ? 'purchase' : 'sale'; - $table = ($type === 'purchase') ? 'purchases' : 'invoices'; - $item_table = ($type === 'purchase') ? 'purchase_items' : 'invoice_items'; - $fk_col = ($type === 'purchase') ? 'purchase_id' : 'invoice_id'; - - db()->prepare("DELETE FROM $table WHERE id = ?")->execute([$id]); - db()->prepare("DELETE FROM $item_table WHERE $fk_col = ?")->execute([$id]); - redirectWithMessage(($type === 'purchase' ? "Purchase" : "Invoice") . " deleted!", "index.php?page=" . ($type === 'purchase' ? 'purchases' : 'sales')); - } - if (isset($_POST['delete_quotation'])) { $id = (int)$_POST['id']; db()->prepare("DELETE FROM quotations WHERE id = ?")->execute([$id]); @@ -2927,118 +2817,6 @@ function getPromotionalPrice($item) { $message = "LPO deleted!"; } - if (isset($_POST['convert_to_invoice'])) { - $db = db(); - try { - $db->beginTransaction(); - $quot_id = (int)$_POST['quotation_id']; - - $stmt = $db->prepare("SELECT * FROM quotations WHERE id = ?"); - $stmt->execute([$quot_id]); - $quot = $stmt->fetch(); - - if (!$quot) throw new Exception("Quotation not found."); - if ($quot['status'] === 'converted') throw new Exception("Quotation already converted."); - - $stmtItems = $db->prepare("SELECT * FROM quotation_items WHERE quotation_id = ?"); - $stmtItems->execute([$quot_id]); - $qItems = $stmtItems->fetchAll(); - - // Create Invoice - $inv_date = date('Y-m-d'); - $stmtInv = $db->prepare("INSERT INTO invoices (customer_id, invoice_date, status, payment_type, total_amount, vat_amount, total_with_vat, paid_amount, outlet_id) VALUES (?, ?, 'unpaid', 'credit', ?, ?, ?, 0, ?)"); - $stmtInv->execute([$quot['customer_id'], $inv_date, $quot['total_amount'], $quot['vat_amount'], $quot['total_with_vat'], current_outlet_id()]); - $inv_id = $db->lastInsertId(); - - $items_for_journal = []; - foreach ($qItems as $item) { - $lineVatAmount = line_item_vat_amount($db, $item); - $db->prepare("INSERT INTO invoice_items (invoice_id, item_id, quantity, unit_price, vat_amount, total_price) VALUES (?, ?, ?, ?, ?, ?)")->execute([$inv_id, $item['item_id'], $item['quantity'], $item['unit_price'], $lineVatAmount, $item['total_price']]); - - // Update stock - update_stock($item['item_id'], -$item['quantity']); - $items_for_journal[] = ['id' => $item['item_id'], 'qty' => $item['quantity']]; - } - - // Update Quotation status - $db->prepare("UPDATE quotations SET status = 'converted' WHERE id = ?")->execute([$quot_id]); - - // Accounting - recordSaleJournal($inv_id, $quot['total_with_vat'], $inv_date, $items_for_journal, $quot['vat_amount']); - - $db->commit(); - $message = "Quotation converted to Invoice #$inv_id successfully!"; - } catch (Exception $e) { $db->rollBack(); $message = "Error: " . $e->getMessage(); } - } - - if (isset($_POST['convert_lpo_to_purchase'])) { - $db = db(); - try { - $db->beginTransaction(); - $lpo_id = (int)$_POST['lpo_id']; - - $stmt = $db->prepare("SELECT * FROM lpos WHERE id = ?"); - $stmt->execute([$lpo_id]); - $lpo = $stmt->fetch(); - - if (!$lpo) throw new Exception("LPO not found."); - if ($lpo['status'] === 'converted') throw new Exception("LPO already converted."); - - $stmtItems = $db->prepare("SELECT * FROM lpo_items WHERE lpo_id = ?"); - $stmtItems->execute([$lpo_id]); - $lItems = $stmtItems->fetchAll(); - - // Create Purchase Invoice - $inv_date = date('Y-m-d'); - $stmtPur = $db->prepare("INSERT INTO purchases (supplier_id, invoice_date, status, payment_type, total_amount, vat_amount, total_with_vat, paid_amount, outlet_id) VALUES (?, ?, 'unpaid', 'credit', ?, ?, ?, 0, ?)"); - $stmtPur->execute([$lpo['supplier_id'], $inv_date, $lpo['total_amount'], $lpo['vat_amount'], $lpo['total_with_vat'], current_outlet_id()]); - $pur_id = $db->lastInsertId(); - - $items_for_journal = []; - foreach ($lItems as $item) { - $db->prepare("INSERT INTO purchase_items (purchase_id, item_id, quantity, unit_price, vat_amount, total_price) VALUES (?, ?, ?, ?, ?, ?)")->execute([$pur_id, $item['item_id'], $item['quantity'], $item['unit_price'], $item['vat_amount'], $item['total_amount']]); - - // Update stock - update_stock($item['item_id'], $item['quantity']); - $items_for_journal[] = ['id' => $item['item_id'], 'qty' => $item['quantity']]; - } - - // Update LPO status - $db->prepare("UPDATE lpos SET status = 'converted' WHERE id = ?")->execute([$lpo_id]); - - // Accounting (if exists) - if (function_exists('recordPurchaseJournal')) { - recordPurchaseJournal($pur_id, $lpo['total_with_vat'], $inv_date, $items_for_journal, $lpo['vat_amount']); - } - - $db->commit(); - $message = "LPO converted to Purchase Invoice #$pur_id successfully!"; - header("Location: index.php?page=purchases"); - exit; - } catch (Exception $e) { $db->rollBack(); $message = "Error: " . $e->getMessage(); } - } - - if (isset($_POST['record_payment'])) { - $id = (int)$_POST['invoice_id']; - $amount = (float)$_POST['amount']; - $date = $_POST['payment_date'] ?: date('Y-m-d'); - $method = $_POST['payment_method'] ?? 'Cash'; - $type = ($page === 'purchases') ? 'purchase' : 'sale'; - $table = ($type === 'purchase') ? 'purchases' : 'invoices'; - $payment_table = ($type === 'purchase') ? 'purchase_payments' : 'payments'; - $fk_col = ($type === 'purchase') ? 'purchase_id' : 'invoice_id'; - - $db = db(); - $db->prepare("INSERT INTO $payment_table ($fk_col, amount, payment_date, payment_method, notes) VALUES (?, ?, ?, ?, ?)")->execute([$id, $amount, $date, $method, $_POST['notes'] ?? '']); - $pay_id = $db->lastInsertId(); - $db->prepare("UPDATE $table SET paid_amount = paid_amount + ?, status = IF(paid_amount + ? >= total_with_vat, 'paid', 'partially_paid') WHERE id = ?")->execute([$amount, $amount, $id]); - - if ($type === 'sale') recordPaymentReceivedJournal((int)$pay_id, $amount, $date, $method); - else recordPaymentMadeJournal((int)$pay_id, $amount, $date, $method); - $message = "Payment recorded!"; - $_SESSION['trigger_receipt_modal'] = true; $_SESSION['show_receipt_id'] = $pay_id; - } - if (isset($_POST['add_expense'])) { $amt = (float)$_POST['amount']; $date = $_POST['expense_date'] ?: date('Y-m-d'); @@ -3562,48 +3340,7 @@ if (isset($_POST['add_hr_department'])) { } } - if (isset($_POST['update_settings'])) { - if (can('settings_view')) { - $db = db(); - if (isset($_POST['settings']) && is_array($_POST['settings'])) { - $settings = $_POST['settings']; - $settings['weight_barcode_mode'] = in_array(($settings['weight_barcode_mode'] ?? 'weight'), ['weight', 'price'], true) ? $settings['weight_barcode_mode'] : 'weight'; - $licenseAppName = trim((string)($settings['license_app_name'] ?? '')); - $settings['license_app_name'] = $licenseAppName !== '' ? substr($licenseAppName, 0, 190) : ''; - $licenseAppSlug = trim((string)($settings['license_app_slug'] ?? '')); - $settings['license_app_slug'] = $licenseAppSlug !== '' ? LicenseService::sanitizeAppSlug($licenseAppSlug, true) : ''; - $prefixStart = (int)($settings['weight_barcode_prefix_start'] ?? 20); - $prefixEnd = (int)($settings['weight_barcode_prefix_end'] ?? 29); - if ($prefixStart < 20 || $prefixStart > 29) $prefixStart = 20; - if ($prefixEnd < 20 || $prefixEnd > 29) $prefixEnd = 29; - if ($prefixStart > $prefixEnd) { - [$prefixStart, $prefixEnd] = [$prefixEnd, $prefixStart]; - } - $settings['weight_barcode_prefix_start'] = (string)$prefixStart; - $settings['weight_barcode_prefix_end'] = (string)$prefixEnd; - - foreach ($settings as $key => $value) { - $stmt = $db->prepare("INSERT INTO settings (`key`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = ?"); - $stmt->execute([$key, $value, $value]); - } - } - - // Handle file uploads - $files = ['company_logo', 'favicon', 'manager_signature', 'display_slide_1', 'display_slide_2', 'display_slide_3']; - foreach ($files as $file_key) { - if (isset($_FILES[$file_key]) && $_FILES[$file_key]['error'] === 0) { - $ext = pathinfo($_FILES[$file_key]['name'], PATHINFO_EXTENSION); - $filename = 'uploads/' . $file_key . '_' . time() . '.' . $ext; - if (!is_dir('uploads')) mkdir('uploads', 0777, true); - if (move_uploaded_file($_FILES[$file_key]['tmp_name'], $filename)) { - $stmt = $db->prepare("INSERT INTO settings (`key`, `value`) VALUES (?, ?) ON DUPLICATE KEY UPDATE `value` = ?"); - $stmt->execute([$file_key, $filename, $filename]); - } - } - } - redirectWithMessage("Settings updated successfully!", "index.php?page=settings"); - } - } + require 'pages/settings_save_logic.php'; // --- Backup Handlers --- if (isset($_POST['create_backup'])) { @@ -3805,7 +3542,7 @@ if (isset($_POST['add_hr_department'])) { $stmt->execute([$register_id, $user_id, $opening_balance]); $_SESSION['register_session_id'] = db()->lastInsertId(); $message = "Register opened successfully!"; - header("Location: index.php?page=pos"); + header("Location: " . page_url("pos")); exit; } } @@ -3839,10 +3576,10 @@ if (isset($_POST['add_hr_department'])) { if ($redirect_to === 'dashboard') { // For POS users, we want dashboard - header("Location: index.php?page=dashboard"); + header("Location: " . page_url("dashboard")); } else { // For Admin, we stay on sessions page - redirectWithMessage($message, "index.php?page=" . urlencode($redirect_to)); + redirectWithMessage($message, page_url((string)$redirect_to)); } exit; } @@ -4478,7 +4215,7 @@ switch ($page) { db()->prepare("DELETE FROM outlets WHERE id = ?")->execute([$id]); } } - header("Location: index.php?page=outlets"); + header("Location: " . page_url("outlets")); exit; } $countStmt = db()->query("SELECT COUNT(*) FROM outlets"); @@ -5422,7 +5159,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
. - +
@@ -5433,13 +5170,13 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';