From 9ef5db2b9aafd8b1f2fb264dbabdfd8d3d0d3b0a Mon Sep 17 00:00:00 2001 From: Flatlogic Bot Date: Tue, 17 Mar 2026 10:11:45 +0000 Subject: [PATCH] Autosave: 20260317-101145 --- api/chat.php | 64 ++++++++++++++++++++++++++++ api/telegram_webhook.php | 91 ++++++++++++++++++++++++++++++++++++++++ assets/js/main.js | 4 +- debug.log | 2 + index.php | 32 ++++++++------ post_debug.log | 3 ++ summary.txt | 21 ++++++---- 7 files changed, 194 insertions(+), 23 deletions(-) create mode 100644 api/chat.php create mode 100644 api/telegram_webhook.php diff --git a/api/chat.php b/api/chat.php new file mode 100644 index 0000000..dbe026c --- /dev/null +++ b/api/chat.php @@ -0,0 +1,64 @@ + "I didn't catch that. Could you repeat?"]); + exit; +} + +try { + // 1. Fetch Knowledge Base (FAQs) + $stmt = db()->query("SELECT keywords, answer FROM faqs"); + $faqs = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $knowledgeBase = "Here is the knowledge base for this website:\n\n"; + foreach ($faqs as $faq) { + $knowledgeBase .= "Q: " . $faq['keywords'] . "\nA: " . $faq['answer'] . "\n---\n"; + } + + // 2. Construct Prompt for AI + $systemPrompt = "You are a helpful, friendly AI assistant for this website. " . + "Use the provided Knowledge Base to answer user questions accurately. " . + "If the answer is found in the Knowledge Base, rephrase it naturally. " . + "If the answer is NOT in the Knowledge Base, use your general knowledge to help, " . + "but politely mention that you don't have specific information about that if it seems like a site-specific question. " . + "Keep answers concise and professional.\n\n" . + $knowledgeBase; + + // 3. Call AI API + $response = LocalAIApi::createResponse([ + 'model' => 'gpt-4o-mini', + 'input' => [ + ['role' => 'system', 'content' => $systemPrompt], + ['role' => 'user', 'content' => $message], + ] + ]); + + if (!empty($response['success'])) { + $aiReply = LocalAIApi::extractText($response); + + // 4. Save to Database + try { + $stmt = db()->prepare("INSERT INTO messages (user_message, ai_response) VALUES (?, ?)"); + $stmt->execute([$message, $aiReply]); + } catch (Exception $e) { + error_log("DB Save Error: " . $e->getMessage()); + // Continue even if save fails, so the user still gets a reply + } + + echo json_encode(['reply' => $aiReply]); + } else { + // Fallback if AI fails + error_log("AI Error: " . ($response['error'] ?? 'Unknown')); + echo json_encode(['reply' => "I'm having trouble connecting to my brain right now. Please try again later."]); + } + +} catch (Exception $e) { + error_log("Chat Error: " . $e->getMessage()); + echo json_encode(['reply' => "An internal error occurred."]); +} diff --git a/api/telegram_webhook.php b/api/telegram_webhook.php new file mode 100644 index 0000000..fa4899c --- /dev/null +++ b/api/telegram_webhook.php @@ -0,0 +1,91 @@ +query("SELECT setting_value FROM settings WHERE setting_key = 'telegram_token'"); +$token = $stmt->fetchColumn(); + +if (!$token) { + error_log("Telegram Error: No bot token found in settings."); + exit; +} + +function sendTelegramMessage($chatId, $text, $token) { + $url = "https://api.telegram.org/bot$token/sendMessage"; + $data = [ + 'chat_id' => $chatId, + 'text' => $text, + 'parse_mode' => 'Markdown' + ]; + + $options = [ + 'http' => [ + 'header' => "Content-type: application/x-www-form-urlencoded\r\n", + 'method' => 'POST', + 'content' => http_build_query($data), + ], + ]; + $context = stream_context_create($options); + return file_get_contents($url, false, $context); +} + +// Process with AI (Similar logic to api/chat.php) +try { + // 1. Fetch Knowledge Base + $stmt = db()->query("SELECT keywords, answer FROM faqs"); + $faqs = $stmt->fetchAll(PDO::FETCH_ASSOC); + + $knowledgeBase = "Here is the knowledge base for this website:\n\n"; + foreach ($faqs as $faq) { + $knowledgeBase .= "Q: " . $faq['keywords'] . "\nA: " . $faq['answer'] . "\n---\n"; + } + + $systemPrompt = "You are a helpful AI assistant integrated with Telegram. " . + "Use the provided Knowledge Base to answer user questions. " . + "Keep answers concise for mobile reading. Use Markdown for formatting.\n\n" . + $knowledgeBase; + + // 2. Call AI + $response = LocalAIApi::createResponse([ + 'model' => 'gpt-4o-mini', + 'input' => [ + ['role' => 'system', 'content' => $systemPrompt], + ['role' => 'user', 'content' => $text], + ] + ]); + + if (!empty($response['success'])) { + $aiReply = LocalAIApi::extractText($response); + + // 3. Save History + try { + $stmt = db()->prepare("INSERT INTO messages (user_message, ai_response) VALUES (?, ?)"); + $stmt->execute(["[Telegram] " . $text, $aiReply]); + } catch (Exception $e) {} + + // 4. Send back to Telegram + sendTelegramMessage($chatId, $aiReply, $token); + } else { + sendTelegramMessage($chatId, "I'm sorry, I encountered an error processing your request.", $token); + } + +} catch (Exception $e) { + error_log("Telegram Webhook Error: " . $e->getMessage()); +} diff --git a/assets/js/main.js b/assets/js/main.js index 2975cea..c376a69 100644 --- a/assets/js/main.js +++ b/assets/js/main.js @@ -29,8 +29,8 @@ document.addEventListener('DOMContentLoaded', function() { overlay.addEventListener('click', function() { sidebar.classList.remove('show'); overlay.classList.remove('show'); - }); + }); // Close sidebar when a link is clicked on mobile const sidebarLinks = document.querySelectorAll('.sidebar .nav-link'); sidebarLinks.forEach(link => { @@ -81,10 +81,8 @@ document.addEventListener('DOMContentLoaded', function() { .then(response => response.json()) .then(data => { if (!data.success) { - console.error('Failed to save theme:', data.error); } }) - .catch(err => console.error('Error:', err)); }); }); }); diff --git a/debug.log b/debug.log index 25388d7..71eaccd 100644 --- a/debug.log +++ b/debug.log @@ -3,3 +3,5 @@ 2026-03-01 13:00:29 - Items case hit 2026-03-01 13:17:12 - Items case hit 2026-03-01 18:24:40 - Items case hit +2026-03-17 09:58:59 - Items case hit +2026-03-17 10:04:31 - Items case hit diff --git a/index.php b/index.php index 560064b..cf76357 100644 --- a/index.php +++ b/index.php @@ -286,16 +286,18 @@ function renderPagination($currentPage, $totalPages) { "; @@ -4120,12 +4122,18 @@ switch ($page) { $data['backup_settings'] = $stmt->fetchAll(PDO::FETCH_KEY_PAIR); break; case 'accounting': - $data['journal_entries'] = db()->query("SELECT je.*, + $limit = isset($_GET["limit"]) ? (int)$_GET["limit"] : 20; + $page = isset($_GET["p"]) ? (int)$_GET["p"] : 1; + $offset = ($page - 1) * $limit; + + $totalEntries = db()->query("SELECT COUNT(*) FROM acc_journal_entries")->fetchColumn(); + $data["total_pages"] = ceil($totalEntries / $limit); + $data["current_page"] = $page; + + $data["journal_entries"] = db()->query("SELECT je.*, (SELECT SUM(debit) FROM acc_ledger WHERE journal_entry_id = je.id) as total_debit FROM acc_journal_entries je - ORDER BY je.entry_date DESC, je.id DESC LIMIT 100")->fetchAll(); - $data['accounts'] = db()->query("SELECT * FROM acc_accounts ORDER BY code ASC")->fetchAll(); - + ORDER BY je.entry_date DESC, je.id DESC LIMIT $limit OFFSET $offset")->fetchAll(); if (isset($_GET['action']) && $_GET['action'] === 'get_entry_details') { header('Content-Type: application/json'); $id = (int)$_GET['id']; diff --git a/post_debug.log b/post_debug.log index 6de0d00..7104fe1 100644 --- a/post_debug.log +++ b/post_debug.log @@ -32,3 +32,6 @@ 2026-02-26 17:58:46 - POST: {"username":"admin","password":"admin123","login":""} 2026-02-26 17:59:03 - POST: {"username":"admin","password":"admin123","login":""} 2026-02-26 17:59:14 - POST: {"username":"admin","password":"admin","login":""} +2026-03-17 09:25:20 - POST: {"start_trial":""} +2026-03-17 09:25:46 - POST: {"username":"admin","password":"admin","login":""} +2026-03-17 09:58:21 - POST: {"license_key":"FLAT-8E07-54E9-B427","activate":""} diff --git a/summary.txt b/summary.txt index 5eefc96..7ed5320 100644 --- a/summary.txt +++ b/summary.txt @@ -1,13 +1,18 @@ -Plan: Update the default VAT rate to 0 in adding/editing forms and ensure all VAT fields are formatted to 2 decimals throughout the app. +Plan: + +1. Identified a critical HTML structure error: a missing `` tag in the `accounting` journal table (index.php) was causing the browser to render the page incorrectly, potentially hiding the main content area. +2. Found a JavaScript logic error in the `renderPagination` function where `document.currentScript` was being accessed inside a `DOMContentLoaded` listener (where it is null), causing the "Rows per page" dropdown to remain at the bottom instead of moving above the table. +3. Fixed both issues by patching `index.php`. Changed: -* `index.php`: - - Changed the default `vat_rate` value to `0` in both PHP backend processing and JavaScript calculations. - - Set the HTML input step for `vat_rate` to `0.01` with a default `value="0"`. - - Updated all VAT percentage and VAT amount display formatting to use exactly 2 decimal places (`.toFixed(2)` in JavaScript and `number_format(..., 2)` in PHP) globally. + +* `index.php`: + * Added the missing `` tag to the accounting journal table. + * Updated the `renderPagination` inline script to correctly capture `document.currentScript` immediately and safely move the "Rows per page" dropdown above the table wrapper. Notes: -* This change applies to item forms, shopping cart/POS, sales invoices, purchase invoices, and VAT reporting. -* Reminder: click Save in the editor to sync changes. -Next: Would you like any other form default values or formats adjusted? \ No newline at end of file +* The missing `` tag likely caused the browser to treat the entire main content area as invalid or hidden, explaining why only the sidebar was visible. +* The pagination dropdown should now appear correctly above the table. + +Next: Please verify that the accounting page (`/index.php?page=accounting`) now loads correctly with the sidebar AND the main content table. Also check if the "Rows per page" dropdown is visible above the table.