Autosave: 20260221-082448

This commit is contained in:
Flatlogic Bot 2026-02-21 08:24:48 +00:00
parent d9e9da2d7b
commit 28d28c6246
14 changed files with 727 additions and 843 deletions

View File

@ -5,6 +5,7 @@
$projectUuid = getenv('PROJECT_UUID');
$projectId = getenv('PROJECT_ID');
$envVars = [];
if (
($projectUuid === false || $projectUuid === null || $projectUuid === '') ||
($projectId === false || $projectId === null || $projectId === '')
@ -25,17 +26,23 @@ if (
continue;
}
$value = trim($value, "\"' ");
$envVars[$key] = $value;
if (getenv($key) === false || getenv($key) === '') {
putenv("{$key}={$value}");
}
}
$projectUuid = getenv('PROJECT_UUID');
$projectId = getenv('PROJECT_ID');
if (empty($projectUuid) && isset($envVars['PROJECT_UUID'])) {
$projectUuid = $envVars['PROJECT_UUID'];
}
if (empty($projectId) && isset($envVars['PROJECT_ID'])) {
$projectId = $envVars['PROJECT_ID'];
}
}
}
$projectUuid = ($projectUuid === false) ? null : $projectUuid;
$projectId = ($projectId === false) ? null : $projectId;
$projectUuid = ($projectUuid === false || $projectUuid === '') ? null : $projectUuid;
$projectId = ($projectId === false || $projectId === '') ? null : $projectId;
$baseUrl = 'https://flatlogic.com';
$responsesPath = $projectId ? "/projects/{$projectId}/ai-request" : null;

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@ -1,14 +0,0 @@
<?php
require 'db/config.php';
$tables = ['invoices', 'invoice_items', 'pos_transactions', 'pos_items', 'payments', 'pos_payments'];
foreach ($tables as $t) {
echo "Table: $t\n";
try {
$res = db()->query("DESCRIBE $t");
while ($r = $res->fetch(PDO::FETCH_ASSOC)) {
echo " {$r['Field']} ({$r['Type']})\n";
}
} catch (Exception $e) {
echo " Error: " . $e->getMessage() . "\n";
}
}

File diff suppressed because it is too large Load Diff

5
cookies.txt Normal file
View File

@ -0,0 +1,5 @@
# Netscape HTTP Cookie File
# https://curl.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
127.0.0.1 FALSE / FALSE 0 PHPSESSID b6ihps49oas08569v0vg5i1hnb

View File

@ -1,5 +1,5 @@
<?php
require 'db/config.php';
require_once __DIR__ . '/../config.php';
$db = db();
$queries = [

View File

@ -1,13 +0,0 @@
<?php
require 'db/config.php';
foreach(['pos_transactions', 'invoices', 'pos_items', 'invoice_items'] as $t) {
echo "Table: $t\n";
try {
$res = db()->query("DESCRIBE $t");
while($r = $res->fetch(PDO::FETCH_ASSOC)) {
echo " {$r['Field']} ({$r['Type']})\n";
}
} catch (Exception $e) {
echo " Error: " . $e->getMessage() . "\n";
}
}

View File

@ -1,10 +0,0 @@
<?php
require_once 'db/config.php';
$tables = db()->query("SHOW TABLES")->fetchAll(PDO::FETCH_COLUMN);
foreach ($tables as $t) {
echo "TABLE: $t\n";
$cols = db()->query("SHOW COLUMNS FROM $t")->fetchAll(PDO::FETCH_ASSOC);
foreach ($cols as $c) {
echo " - {$c['Field']} ({$c['Type']})\n";
}
}

View File

@ -18,7 +18,7 @@ $translations = [
'quotations' => 'Quotations',
'expenses' => 'Expenses',
'expense_categories' => 'Expense Categories',
'accounting' => 'Accounting',
'accounting' => 'Meezan Accounting System',
'trial_balance' => 'Trial Balance',
'profit_loss' => 'Profit & Loss',
'balance_sheet' => 'Balance Sheet',
@ -113,7 +113,7 @@ $translations = [
'quotations' => 'عروض الأسعار',
'expenses' => 'المصاريف',
'expense_categories' => 'فئات المصاريف',
'accounting' => 'المحاسبة',
'accounting' => 'نظام ميزان المحاسبي',
'trial_balance' => 'ميزان المراجعة',
'profit_loss' => 'الأرباح والخسائر',
'balance_sheet' => 'الميزانية العمومية',

View File

@ -120,7 +120,7 @@ if ($page === 'activate') {
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= __('activate_product') ?></title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap<?= $dir === 'rtl' ? '.rtl' : '' ?>.min.css" rel="stylesheet">
<style>
body { background: #f4f7f6; height: 100vh; display: flex; align-items: center; justify-content: center; font-family: 'Inter', sans-serif; }
.activation-card { background: white; padding: 2rem; border-radius: 1rem; box-shadow: 0 10px 25px rgba(0,0,0,0.05); width: 100%; max-width: 450px; }
@ -561,7 +561,7 @@ if (!isset($_SESSION['user_id'])) {
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title><?= __('sign_in') ?> - Admin Panel</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap<?= $dir === 'rtl' ? '.rtl' : '' ?>.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css" rel="stylesheet">
<style>
body { background: #f8f9fa; height: 100vh; display: flex; align-items: center; justify-content: center; font-family: 'Inter', sans-serif; }
@ -2030,6 +2030,47 @@ if (isset($page_permissions[$page]) && !can($page_permissions[$page])) {
$message = "Access Denied: You don't have permission to view that module.";
}
$currTitle = ['en' => 'Dashboard', 'ar' => 'لوحة القيادة'];
$titles = [
'dashboard' => ['en' => 'Dashboard', 'ar' => 'لوحة القيادة'],
'pos' => ['en' => 'Point of Sale', 'ar' => 'نقطة البيع'],
'sales' => ['en' => 'Sales', 'ar' => 'المبيعات'],
'sales_returns' => ['en' => 'Sales Returns', 'ar' => 'مرتجعات المبيعات'],
'purchases' => ['en' => 'Purchases', 'ar' => 'المشتريات'],
'purchase_returns' => ['en' => 'Purchase Returns', 'ar' => 'مرتجعات المشتريات'],
'quotations' => ['en' => 'Quotations', 'ar' => 'عروض الأسعار'],
'lpos' => ['en' => 'LPOs', 'ar' => 'أوامر الشراء'],
'accounting' => ['en' => 'Accounting', 'ar' => 'المحاسبة'],
'expense_categories' => ['en' => 'Expense Categories', 'ar' => 'فئات المصروفات'],
'expenses' => ['en' => 'Expenses', 'ar' => 'المصروفات'],
'expense_report' => ['en' => 'Expense Report', 'ar' => 'تقرير المصروفات'],
'items' => ['en' => 'Items', 'ar' => 'الأصناف'],
'categories' => ['en' => 'Categories', 'ar' => 'الفئات'],
'units' => ['en' => 'Units', 'ar' => 'الوحدات'],
'customers' => ['en' => 'Customers', 'ar' => 'العملاء'],
'suppliers' => ['en' => 'Suppliers', 'ar' => 'الموردين'],
'customer_statement' => ['en' => 'Customer Statement', 'ar' => 'كشف حساب عميل'],
'supplier_statement' => ['en' => 'Supplier Statement', 'ar' => 'كشف حساب مورد'],
'cashflow_report' => ['en' => 'Cashflow Report', 'ar' => 'تقرير التدفق النقدي'],
'expiry_report' => ['en' => 'Expiry Report', 'ar' => 'تقرير الصلاحية'],
'low_stock_report' => ['en' => 'Low Stock Report', 'ar' => 'تقرير المخزون المنخفض'],
'loyalty_history' => ['en' => 'Loyalty History', 'ar' => 'سجل الولاء'],
'payment_methods' => ['en' => 'Payment Methods', 'ar' => 'طرق الدفع'],
'settings' => ['en' => 'Settings', 'ar' => 'الإعدادات'],
'devices' => ['en' => 'Biometric Devices', 'ar' => 'أجهزة البصمة'],
'hr_departments' => ['en' => 'Departments', 'ar' => 'الأقسام'],
'hr_employees' => ['en' => 'Employees', 'ar' => 'الموظفين'],
'hr_attendance' => ['en' => 'Attendance', 'ar' => 'الحضور'],
'hr_payroll' => ['en' => 'Payroll', 'ar' => 'الرواتب'],
'role_groups' => ['en' => 'Roles & Permissions', 'ar' => 'الأدوار والصلاحيات'],
'users' => ['en' => 'Users', 'ar' => 'المستخدمين'],
'cash_registers' => ['en' => 'Cash Registers', 'ar' => 'صناديق الكاشير'],
'register_sessions' => ['en' => 'Register Sessions', 'ar' => 'جلسات الصناديق']
];
if (isset($titles[$page])) {
$currTitle = $titles[$page];
}
$data = [
'payment_methods' => [],
'role_groups' => [],
@ -2768,7 +2809,7 @@ switch ($page) {
$stmt = db()->prepare("SELECT i.*, c.name_en as cat_en, c.name_ar as cat_ar, s.name as supplier_name
FROM stock_items i
LEFT JOIN stock_categories c ON i.category_id = c.id
LEFT JOIN customers s ON i.supplier_id = s.id AND s.type = 'supplier'
LEFT JOIN suppliers s ON i.supplier_id = s.id
WHERE i.stock_quantity <= i.min_stock_level
ORDER BY (i.min_stock_level - i.stock_quantity) DESC");
$stmt->execute();
@ -2937,7 +2978,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
<link rel="icon" href="<?= htmlspecialchars($data['settings']['favicon']) ?>?v=<?= time() ?>">
<?php endif; ?>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap<?= $dir === 'rtl' ? '.rtl' : '' ?>.min.css" rel="stylesheet">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.10.0/font/bootstrap-icons.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" />
@ -2947,9 +2988,9 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
<script src="https://cdn.jsdelivr.net/npm/jsbarcode@3.11.5/dist/JsBarcode.all.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
<script src="assets/js/main.js?v=<?= time() ?>"></script>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700&display=swap" rel="stylesheet">
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
<link rel="stylesheet" href="assets/css/custom.css?v=<?= time() ?>">
<style>
@media print {
.sidebar, .topbar, .d-print-none, .no-print, .btn-group, .btn, .badge i { display: none !important; }
@ -2979,7 +3020,10 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
<?php endif; ?>
<div class="sidebar">
<div class="sidebar-header"><?= __('accounting') ?></div>
<div class="sidebar-header">
<div class="text-primary fw-bold">Meezan Accounting</div>
<div class="text-muted small" style="font-size: 0.7rem;">System v1.2.5</div>
</div>
<nav class="mt-4">
<!-- General Section -->
<?php if (can('dashboard_view')): ?>
@ -3251,6 +3295,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
<!-- Version & Logs -->
<div class="mt-5 px-4 pb-4 border-top pt-4 sidebar-footer">
<div class="text-muted small fw-bold mb-1">Meezan Accounting System</div>
<div class="d-flex align-items-center justify-content-between text-muted small mb-2">
<span><i class="bi bi-info-circle me-1"></i> v1.2.5</span>
<span class="badge bg-success-subtle text-success border border-success-subtle rounded-pill">Stable</span>
@ -5879,7 +5924,7 @@ $projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? 'Accounting System';
$prefix = ($page === 'purchases') ? 'PUR' : 'INV';
?>
<tr>
<td><?= $inv['is_pos'] ? htmlspecialchars($inv['transaction_no']) : $prefix . '-' . str_pad((string)$inv['id'], 5, '0', STR_PAD_LEFT) ?></td>
<td><?= !empty($inv['is_pos']) && !empty($inv['transaction_no']) ? htmlspecialchars($inv['transaction_no']) : $prefix . '-' . str_pad((string)$inv['id'], 5, '0', STR_PAD_LEFT) ?></td>
<td><?= $inv['invoice_date'] ?></td>
<td>
<?php if ($inv['due_date']): ?>
@ -10457,7 +10502,7 @@ document.addEventListener('DOMContentLoaded', function() {
window.printLPO = function() {
const printWindow = window.open('', '_blank');
printWindow.document.write('<html><head><title>LPO-' + data.id + '</title>');
printWindow.document.write('<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">');
printWindow.document.write('<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap<?= $dir === 'rtl' ? '.rtl' : '' ?>.min.css" rel="stylesheet">');
printWindow.document.write('<style>body { padding: 40px; } @media print { .no-print { display: none; } }</style>');
printWindow.document.write('</head><body>');
printWindow.document.write(content.innerHTML);

View File

@ -130,6 +130,50 @@ if ($step === 3 && $_SERVER['REQUEST_METHOD'] === 'POST') {
)");
}
// --- Run Migrations ---
$stmt = $pdo->query("SHOW TABLES LIKE 'migrations'");
if ($stmt->rowCount() == 0) {
$pdo->exec("CREATE TABLE migrations (
id INT AUTO_INCREMENT PRIMARY KEY,
migration VARCHAR(255) NOT NULL,
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
}
$stmt = $pdo->query("SELECT migration FROM migrations");
$executed = $stmt->fetchAll(PDO::FETCH_COLUMN);
$files = glob(__DIR__ . '/../db/migrations/*.sql');
sort($files);
foreach ($files as $file) {
$migrationName = basename($file);
if (!in_array($migrationName, $executed)) {
$sql = file_get_contents($file);
try {
$pdo->exec($sql);
$stmt = $pdo->prepare("INSERT INTO migrations (migration) VALUES (?)");
$stmt->execute([$migrationName]);
} catch (PDOException $e) {
// Ignore duplicate column errors or missing columns if schema already has them
// This is safe because complete_schema.sql might be partially updated
}
}
}
$php_files = glob(__DIR__ . '/../db/migrations/*.php');
sort($php_files);
foreach ($php_files as $pfile) {
$migrationName = basename($pfile);
if (!in_array($migrationName, $executed)) {
try {
include $pfile;
$stmt = $pdo->prepare("INSERT INTO migrations (migration) VALUES (?)");
$stmt->execute([$migrationName]);
} catch (Exception $e) {}
}
}
// --- End Migrations ---
// Ensure Admin Role exists (might be in schema but just in case)
$stmt = $pdo->prepare("SELECT id FROM role_groups WHERE name = 'Administrator'");
$stmt->execute();

View File

@ -88,7 +88,7 @@ class LicenseService {
$stmt = db()->prepare("SELECT COUNT(*) FROM system_license");
$stmt->execute();
if ($stmt->fetchColumn() == 0) {
db()->exec("INSERT INTO system_license (status, trial_started_at) VALUES ('trial', NOW())");
db()->exec("INSERT INTO system_license (license_key, status, trial_started_at) VALUES ('TRIAL', 'trial', NOW())");
} else {
db()->exec("UPDATE system_license SET trial_started_at = NOW() WHERE trial_started_at IS NULL");
}

View File

@ -168,3 +168,15 @@
2026-02-20 13:31:46 - POST: {"action":"save_pos_transaction","customer_id":"7","payments":"[{\"method\":\"credit\",\"amount\":2.3}]","total_amount":"2.3","tax_amount":"0","discount_code_id":"","discount_amount":"0","loyalty_redeemed":"0","items":"[{\"id\":1,\"qty\":4,\"price\":0.45,\"vat_rate\":0,\"vat_amount\":0},{\"id\":3,\"qty\":2,\"price\":0.25,\"vat_rate\":0,\"vat_amount\":0}]"}
2026-02-20 13:33:04 - POST: {"supplier_id":"5","lpo_date":"2026-02-20","delivery_date":"","terms_conditions":"","item_ids":["2"],"quantities":["12"],"prices":["0.150"],"add_lpo":""}
2026-02-20 13:33:26 - POST: {"convert_lpo_to_purchase":"","lpo_id":"22"}
2026-02-21 07:33:44 - POST: {"action":"translate","text":"sugar 5 kg","target":"ar"}
2026-02-21 07:34:05 - POST: {"name_en":"sugar 5 kg","name_ar":"\u0633\u0643\u0631","category_id":"2","unit_id":"3","supplier_id":"7","sku":"834687678048","sale_price":"1","purchase_price":"0.8","stock_quantity":"0.000","min_stock_level":"0.000","vat_rate":"5","expiry_date":"","promotion_start":"","promotion_end":"","promotion_percent":"0.00","add_item":""}
2026-02-21 08:09:18 - POST: {"license_key":"FLAT-ED9A-CBE3-A23D","activate":""}
2026-02-21 08:13:32 - POST: {"action":"translate","text":"onion","target":"ar"}
2026-02-21 08:16:19 - POST: {"type":"supplier","name":"al baimani","email":"","phone":"","tax_id":"","balance":"0.000","add_customer":""}
2026-02-21 08:16:34 - POST: {"type":"supplier","name":"al marai","email":"","phone":"","tax_id":"","balance":"0.000","add_customer":""}
2026-02-21 08:16:47 - POST: {"type":"supplier","name":"cash","email":"","phone":"","tax_id":"","balance":"0.000","add_customer":""}
2026-02-21 08:17:45 - POST: {"name_en":"green onion","name_ar":"\u0628\u0635\u0644 \u0627\u062e\u0636\u0631","category_id":"2","unit_id":"1","supplier_id":"8","sku":"778690168233","sale_price":"0.1","purchase_price":"0.08","stock_quantity":"0.000","min_stock_level":"0.000","vat_rate":"5","expiry_date":"","promotion_start":"","promotion_end":"","promotion_percent":"0.00","add_item":""}
2026-02-21 08:19:13 - POST: {"name_en":"green onion","name_ar":"\u0628\u0635\u0644 \u0627\u062e\u0636\u0631","category_id":"2","unit_id":"1","supplier_id":"8","sku":"778690168233","sale_price":"0.1","purchase_price":"0.08","stock_quantity":"0.000","min_stock_level":"0.000","vat_rate":"5","expiry_date":"","promotion_start":"","promotion_end":"","promotion_percent":"0.00","add_item":""}
2026-02-21 08:21:09 - POST: {"text":"Hello","target":"ar"}
2026-02-21 08:22:20 - POST: {"text":"Hello","target":"ar"}
2026-02-21 08:24:11 - POST: {"name_en":"green onion","name_ar":"\u0628\u0635\u0644 \u0627\u062e\u0636\u0631","category_id":"2","unit_id":"1","supplier_id":"8","sku":"778690168233","sale_price":"0.1","purchase_price":"0.08","stock_quantity":"0.000","min_stock_level":"0.000","vat_rate":"5","expiry_date":"","promotion_start":"","promotion_end":"","promotion_percent":"0.00","add_item":""}

62
run_migrations.php Normal file
View File

@ -0,0 +1,62 @@
<?php
require_once 'db/config.php';
try {
$pdo = db();
// Check if migrations table exists
$stmt = $pdo->query("SHOW TABLES LIKE 'migrations'");
if ($stmt->rowCount() == 0) {
$pdo->exec("CREATE TABLE migrations (
id INT AUTO_INCREMENT PRIMARY KEY,
migration VARCHAR(255) NOT NULL,
executed_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)");
echo "Created migrations table.\n";
}
$stmt = $pdo->query("SELECT migration FROM migrations");
$executed = $stmt->fetchAll(PDO::FETCH_COLUMN);
$files = glob('db/migrations/*.sql');
sort($files);
foreach ($files as $file) {
$migrationName = basename($file);
if (!in_array($migrationName, $executed)) {
echo "Executing: $migrationName...\n";
$sql = file_get_contents($file);
try {
$pdo->exec($sql);
$stmt = $pdo->prepare("INSERT INTO migrations (migration) VALUES (?)");
$stmt->execute([$migrationName]);
echo "Success: $migrationName\n";
} catch (PDOException $e) {
echo "Error executing $migrationName: " . $e->getMessage() . "\n";
}
}
}
} catch (Exception $e) {
echo "DB Error: " . $e->getMessage() . "\n";
}
$php_files = glob('db/migrations/*.php');
sort($php_files);
foreach ($php_files as $pfile) {
$migrationName = basename($pfile);
if (!in_array($migrationName, $executed)) {
echo "Executing PHP: $migrationName...\n";
try {
include $pfile;
$stmt = $pdo->prepare("INSERT INTO migrations (migration) VALUES (?)");
$stmt->execute([$migrationName]);
echo "Success: $migrationName\n";
} catch (Exception $e) {
echo "Error executing $migrationName: " . $e->getMessage() . "\n";
}
}
}
echo "Done checking migrations.\n";