Compare commits
No commits in common. "ai-dev" and "master" have entirely different histories.
169
api/chat.php
169
api/chat.php
@ -1,159 +1,64 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
header('Content-Type: application/json; charset=utf-8');
|
||||
|
||||
require_once __DIR__ . '/../db/schema.php';
|
||||
header('Content-Type: application/json');
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../ai/LocalAIApi.php';
|
||||
|
||||
function findFaqReply(array $faqs, string $message): string
|
||||
{
|
||||
$normalizedMessage = function_exists('mb_strtolower')
|
||||
? mb_strtolower($message, 'UTF-8')
|
||||
: strtolower($message);
|
||||
$input = json_decode(file_get_contents('php://input'), true);
|
||||
$message = $input['message'] ?? '';
|
||||
|
||||
foreach ($faqs as $faq) {
|
||||
$keywords = isset($faq['keywords']) && is_string($faq['keywords'])
|
||||
? preg_split('/\s*,\s*/', $faq['keywords'])
|
||||
: [];
|
||||
|
||||
foreach ($keywords as $keyword) {
|
||||
if (!is_string($keyword) || $keyword === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$needle = function_exists('mb_strtolower')
|
||||
? mb_strtolower($keyword, 'UTF-8')
|
||||
: strtolower($keyword);
|
||||
|
||||
$found = function_exists('mb_strpos')
|
||||
? mb_strpos($normalizedMessage, $needle, 0, 'UTF-8') !== false
|
||||
: strpos($normalizedMessage, $needle) !== false;
|
||||
|
||||
if ($needle !== '' && $found) {
|
||||
return (string) ($faq['answer'] ?? '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
$rawInput = file_get_contents('php://input');
|
||||
$input = json_decode($rawInput ?: '', true);
|
||||
$message = '';
|
||||
|
||||
if (is_array($input) && isset($input['message']) && is_string($input['message'])) {
|
||||
$message = trim($input['message']);
|
||||
}
|
||||
|
||||
if ($message === '') {
|
||||
echo json_encode(['reply' => 'Silakan tulis pertanyaan Anda terlebih dahulu.'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
if (empty($message)) {
|
||||
echo json_encode(['reply' => "I didn't catch that. Could you repeat?"]);
|
||||
exit;
|
||||
}
|
||||
|
||||
try {
|
||||
ensureSupportSchema();
|
||||
// 1. Fetch Knowledge Base (FAQs)
|
||||
$stmt = db()->query("SELECT keywords, answer FROM faqs");
|
||||
$faqs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$faqs = [];
|
||||
try {
|
||||
$stmt = db()->query('SELECT keywords, answer FROM faqs ORDER BY id ASC');
|
||||
$faqs = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
|
||||
} catch (Throwable $faqError) {
|
||||
error_log('FAQ Load Error: ' . $faqError->getMessage());
|
||||
}
|
||||
|
||||
$faqReply = findFaqReply($faqs, $message);
|
||||
if ($faqReply !== '') {
|
||||
try {
|
||||
$stmt = db()->prepare('INSERT INTO messages (user_message, ai_response) VALUES (:user_message, :ai_response)');
|
||||
$stmt->bindValue(':user_message', $message);
|
||||
$stmt->bindValue(':ai_response', $faqReply);
|
||||
$stmt->execute();
|
||||
} catch (Throwable $saveError) {
|
||||
error_log('DB Save Error: ' . $saveError->getMessage());
|
||||
}
|
||||
|
||||
echo json_encode(['reply' => $faqReply], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
exit;
|
||||
}
|
||||
|
||||
$knowledgeBase = "Berikut knowledge base website ini:
|
||||
|
||||
";
|
||||
if ($faqs === []) {
|
||||
$knowledgeBase .= "- Belum ada FAQ khusus yang dikonfigurasi.
|
||||
";
|
||||
} else {
|
||||
$knowledgeBase = "Here is the knowledge base for this website:\n\n";
|
||||
foreach ($faqs as $faq) {
|
||||
$knowledgeBase .= 'Q: ' . ($faq['keywords'] ?? '') . "
|
||||
";
|
||||
$knowledgeBase .= 'A: ' . ($faq['answer'] ?? '') . "
|
||||
---
|
||||
";
|
||||
}
|
||||
$knowledgeBase .= "Q: " . $faq['keywords'] . "\nA: " . $faq['answer'] . "\n---\n";
|
||||
}
|
||||
|
||||
$systemPrompt = "Anda adalah asisten AI yang ramah untuk website ini. "
|
||||
. "Gunakan knowledge base bila jawabannya tersedia. "
|
||||
. "Jika pertanyaan tidak ada di knowledge base, bantu secara umum dan jelaskan dengan singkat. "
|
||||
. "Jawab singkat, jelas, dan profesional dalam Bahasa Indonesia.
|
||||
// 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;
|
||||
|
||||
"
|
||||
. $knowledgeBase;
|
||||
|
||||
$response = LocalAIApi::createResponse(
|
||||
[
|
||||
// 3. Call AI API
|
||||
$response = LocalAIApi::createResponse([
|
||||
'model' => 'gpt-4o-mini',
|
||||
'input' => [
|
||||
['role' => 'system', 'content' => $systemPrompt],
|
||||
['role' => 'user', 'content' => $message],
|
||||
],
|
||||
],
|
||||
[
|
||||
'poll_interval' => 2,
|
||||
'poll_timeout' => 45,
|
||||
]
|
||||
);
|
||||
]);
|
||||
|
||||
if (!empty($response['success'])) {
|
||||
$aiReply = LocalAIApi::extractText($response);
|
||||
if ($aiReply === '') {
|
||||
$decoded = LocalAIApi::decodeJsonFromResponse($response);
|
||||
if ($decoded) {
|
||||
$aiReply = json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
}
|
||||
if ($aiReply === '') {
|
||||
$aiReply = 'Pesan Anda sudah diterima, tetapi balasan otomatis belum tersedia saat ini.';
|
||||
}
|
||||
|
||||
// 4. Save to Database
|
||||
try {
|
||||
$stmt = db()->prepare('INSERT INTO messages (user_message, ai_response) VALUES (:user_message, :ai_response)');
|
||||
$stmt->bindValue(':user_message', $message);
|
||||
$stmt->bindValue(':ai_response', $aiReply);
|
||||
$stmt->execute();
|
||||
} catch (Throwable $saveError) {
|
||||
error_log('DB Save Error: ' . $saveError->getMessage());
|
||||
$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], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
exit;
|
||||
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."]);
|
||||
}
|
||||
|
||||
error_log('AI Error: ' . ($response['error'] ?? 'Unknown'));
|
||||
$fallbackReply = 'Saya belum bisa membalas otomatis saat ini. Silakan coba lagi sebentar lagi.';
|
||||
|
||||
try {
|
||||
$stmt = db()->prepare('INSERT INTO messages (user_message, ai_response) VALUES (:user_message, :ai_response)');
|
||||
$stmt->bindValue(':user_message', $message);
|
||||
$stmt->bindValue(':ai_response', $fallbackReply);
|
||||
$stmt->execute();
|
||||
} catch (Throwable $saveError) {
|
||||
error_log('DB Save Error: ' . $saveError->getMessage());
|
||||
}
|
||||
|
||||
echo json_encode(['reply' => $fallbackReply], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
} catch (Throwable $error) {
|
||||
error_log('Chat Error: ' . $error->getMessage());
|
||||
echo json_encode(['reply' => 'Terjadi kesalahan internal. Silakan coba lagi.'], JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
} catch (Exception $e) {
|
||||
error_log("Chat Error: " . $e->getMessage());
|
||||
echo json_encode(['reply' => "An internal error occurred."]);
|
||||
}
|
||||
|
||||
@ -1,180 +1,91 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/../db/schema.php';
|
||||
require_once __DIR__ . '/../db/config.php';
|
||||
require_once __DIR__ . '/../ai/LocalAIApi.php';
|
||||
|
||||
function sendTelegramMessage(int|string $chatId, string $text, string $token): bool
|
||||
{
|
||||
$url = "https://api.telegram.org/bot{$token}/sendMessage";
|
||||
$data = [
|
||||
'chat_id' => $chatId,
|
||||
'text' => $text,
|
||||
];
|
||||
// Get Telegram Update
|
||||
$content = file_get_contents("php://input");
|
||||
$update = json_decode($content, true);
|
||||
|
||||
$options = [
|
||||
'http' => [
|
||||
'header' => "Content-type: application/x-www-form-urlencoded
|
||||
",
|
||||
'method' => 'POST',
|
||||
'content' => http_build_query($data),
|
||||
'timeout' => 20,
|
||||
],
|
||||
];
|
||||
|
||||
$context = stream_context_create($options);
|
||||
$result = @file_get_contents($url, false, $context);
|
||||
|
||||
return $result !== false;
|
||||
}
|
||||
|
||||
function findFaqReply(array $faqs, string $message): string
|
||||
{
|
||||
$normalizedMessage = function_exists('mb_strtolower')
|
||||
? mb_strtolower($message, 'UTF-8')
|
||||
: strtolower($message);
|
||||
|
||||
foreach ($faqs as $faq) {
|
||||
$keywords = isset($faq['keywords']) && is_string($faq['keywords'])
|
||||
? preg_split('/\s*,\s*/', $faq['keywords'])
|
||||
: [];
|
||||
|
||||
foreach ($keywords as $keyword) {
|
||||
if (!is_string($keyword) || $keyword === '') {
|
||||
continue;
|
||||
}
|
||||
|
||||
$needle = function_exists('mb_strtolower')
|
||||
? mb_strtolower($keyword, 'UTF-8')
|
||||
: strtolower($keyword);
|
||||
|
||||
$found = function_exists('mb_strpos')
|
||||
? mb_strpos($normalizedMessage, $needle, 0, 'UTF-8') !== false
|
||||
: strpos($normalizedMessage, $needle) !== false;
|
||||
|
||||
if ($needle !== '' && $found) {
|
||||
return (string) ($faq['answer'] ?? '');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
$content = file_get_contents('php://input');
|
||||
$update = json_decode($content ?: '', true);
|
||||
|
||||
if (!is_array($update) || !isset($update['message']) || !is_array($update['message'])) {
|
||||
if (!$update || !isset($update['message'])) {
|
||||
exit;
|
||||
}
|
||||
|
||||
$message = $update['message'];
|
||||
$chatId = $message['chat']['id'] ?? null;
|
||||
$text = isset($message['text']) && is_string($message['text']) ? trim($message['text']) : '';
|
||||
$chatId = $message['chat']['id'];
|
||||
$text = $message['text'] ?? '';
|
||||
|
||||
if ($chatId === null || $text === '') {
|
||||
if (empty($text)) {
|
||||
exit;
|
||||
}
|
||||
|
||||
// Get Telegram Token from DB
|
||||
$stmt = db()->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 {
|
||||
ensureSupportSchema();
|
||||
// 1. Fetch Knowledge Base
|
||||
$stmt = db()->query("SELECT keywords, answer FROM faqs");
|
||||
$faqs = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
|
||||
$stmt = db()->prepare('SELECT setting_value FROM settings WHERE setting_key = :setting_key LIMIT 1');
|
||||
$stmt->bindValue(':setting_key', 'telegram_token');
|
||||
$stmt->execute();
|
||||
$token = (string) ($stmt->fetchColumn() ?: '');
|
||||
|
||||
if ($token === '') {
|
||||
error_log('Telegram Error: No bot token found in settings.');
|
||||
exit;
|
||||
}
|
||||
|
||||
$faqs = [];
|
||||
try {
|
||||
$stmt = db()->query('SELECT keywords, answer FROM faqs ORDER BY id ASC');
|
||||
$faqs = $stmt->fetchAll(PDO::FETCH_ASSOC) ?: [];
|
||||
} catch (Throwable $faqError) {
|
||||
error_log('Telegram FAQ Load Error: ' . $faqError->getMessage());
|
||||
}
|
||||
|
||||
$faqReply = findFaqReply($faqs, $text);
|
||||
if ($faqReply !== '') {
|
||||
try {
|
||||
$stmt = db()->prepare('INSERT INTO messages (user_message, ai_response) VALUES (:user_message, :ai_response)');
|
||||
$stmt->bindValue(':user_message', '[Telegram] ' . $text);
|
||||
$stmt->bindValue(':ai_response', $faqReply);
|
||||
$stmt->execute();
|
||||
} catch (Throwable $saveError) {
|
||||
error_log('Telegram Save Error: ' . $saveError->getMessage());
|
||||
}
|
||||
|
||||
sendTelegramMessage($chatId, $faqReply, $token);
|
||||
exit;
|
||||
}
|
||||
|
||||
$knowledgeBase = "Berikut knowledge base website ini:
|
||||
|
||||
";
|
||||
if ($faqs === []) {
|
||||
$knowledgeBase .= "- Belum ada FAQ khusus yang dikonfigurasi.
|
||||
";
|
||||
} else {
|
||||
$knowledgeBase = "Here is the knowledge base for this website:\n\n";
|
||||
foreach ($faqs as $faq) {
|
||||
$knowledgeBase .= 'Q: ' . ($faq['keywords'] ?? '') . "
|
||||
";
|
||||
$knowledgeBase .= 'A: ' . ($faq['answer'] ?? '') . "
|
||||
---
|
||||
";
|
||||
}
|
||||
$knowledgeBase .= "Q: " . $faq['keywords'] . "\nA: " . $faq['answer'] . "\n---\n";
|
||||
}
|
||||
|
||||
$systemPrompt = "Anda adalah asisten AI Telegram untuk website ini. "
|
||||
. "Gunakan knowledge base bila relevan. "
|
||||
. "Jawab ringkas, jelas, dan profesional dalam Bahasa Indonesia.
|
||||
$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;
|
||||
|
||||
"
|
||||
. $knowledgeBase;
|
||||
|
||||
$response = LocalAIApi::createResponse(
|
||||
[
|
||||
// 2. Call AI
|
||||
$response = LocalAIApi::createResponse([
|
||||
'model' => 'gpt-4o-mini',
|
||||
'input' => [
|
||||
['role' => 'system', 'content' => $systemPrompt],
|
||||
['role' => 'user', 'content' => $text],
|
||||
],
|
||||
],
|
||||
[
|
||||
'poll_interval' => 2,
|
||||
'poll_timeout' => 45,
|
||||
]
|
||||
);
|
||||
]);
|
||||
|
||||
if (!empty($response['success'])) {
|
||||
$aiReply = LocalAIApi::extractText($response);
|
||||
if ($aiReply === '') {
|
||||
$decoded = LocalAIApi::decodeJsonFromResponse($response);
|
||||
if ($decoded) {
|
||||
$aiReply = json_encode($decoded, JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
}
|
||||
if ($aiReply === '') {
|
||||
$aiReply = 'Pesan Anda sudah diterima, tetapi balasan otomatis belum tersedia saat ini.';
|
||||
}
|
||||
|
||||
// 3. Save History
|
||||
try {
|
||||
$stmt = db()->prepare('INSERT INTO messages (user_message, ai_response) VALUES (:user_message, :ai_response)');
|
||||
$stmt->bindValue(':user_message', '[Telegram] ' . $text);
|
||||
$stmt->bindValue(':ai_response', $aiReply);
|
||||
$stmt->execute();
|
||||
} catch (Throwable $saveError) {
|
||||
error_log('Telegram Save Error: ' . $saveError->getMessage());
|
||||
}
|
||||
$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);
|
||||
exit;
|
||||
} else {
|
||||
sendTelegramMessage($chatId, "I'm sorry, I encountered an error processing your request.", $token);
|
||||
}
|
||||
|
||||
error_log('Telegram AI Error: ' . ($response['error'] ?? 'Unknown'));
|
||||
sendTelegramMessage($chatId, 'Maaf, saya belum bisa memproses permintaan Anda saat ini.', $token);
|
||||
} catch (Throwable $error) {
|
||||
error_log('Telegram Webhook Error: ' . $error->getMessage());
|
||||
} catch (Exception $e) {
|
||||
error_log("Telegram Webhook Error: " . $e->getMessage());
|
||||
}
|
||||
|
||||
@ -1,23 +0,0 @@
|
||||
-- Bootstrap tables required by the built-in chat and Telegram integrations.
|
||||
CREATE TABLE IF NOT EXISTS faqs (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
keywords VARCHAR(255) NOT NULL,
|
||||
answer TEXT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
user_message TEXT NOT NULL,
|
||||
ai_response MEDIUMTEXT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_messages_created_at (created_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
setting_key VARCHAR(100) NOT NULL,
|
||||
setting_value TEXT NULL,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uniq_settings_key (setting_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
@ -1,81 +0,0 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
require_once __DIR__ . '/config.php';
|
||||
|
||||
function ensureSupportSchema(): void
|
||||
{
|
||||
static $bootstrapped = false;
|
||||
|
||||
if ($bootstrapped) {
|
||||
return;
|
||||
}
|
||||
|
||||
$fallbackSql = <<<'SQL'
|
||||
CREATE TABLE IF NOT EXISTS faqs (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
keywords VARCHAR(255) NOT NULL,
|
||||
answer TEXT NOT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS messages (
|
||||
id BIGINT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
user_message TEXT NOT NULL,
|
||||
ai_response MEDIUMTEXT NULL,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
INDEX idx_messages_created_at (created_at)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
|
||||
CREATE TABLE IF NOT EXISTS settings (
|
||||
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
setting_key VARCHAR(100) NOT NULL,
|
||||
setting_value TEXT NULL,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
|
||||
UNIQUE KEY uniq_settings_key (setting_key)
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
|
||||
SQL;
|
||||
|
||||
$migrationPath = __DIR__ . '/migrations/20260512_001_support_tables.sql';
|
||||
$sql = $fallbackSql;
|
||||
|
||||
if (is_readable($migrationPath)) {
|
||||
$fileSql = file_get_contents($migrationPath);
|
||||
if (is_string($fileSql) && trim($fileSql) !== '') {
|
||||
$sql = $fileSql;
|
||||
}
|
||||
}
|
||||
|
||||
db()->exec($sql);
|
||||
|
||||
$faqCount = (int) db()->query('SELECT COUNT(*) FROM faqs')->fetchColumn();
|
||||
if ($faqCount === 0) {
|
||||
$seedFaqs = [
|
||||
[
|
||||
'keywords' => 'penawaran, quotation, quote, harga',
|
||||
'answer' => 'Gunakan modul penawaran untuk membuat penawaran harga barang maupun jasa sebelum pekerjaan dimulai.',
|
||||
],
|
||||
[
|
||||
'keywords' => 'spk, surat perintah kerja, work order',
|
||||
'answer' => 'SPK dipakai untuk menerbitkan perintah kerja berdasarkan penawaran yang sudah disetujui pelanggan.',
|
||||
],
|
||||
[
|
||||
'keywords' => 'surat jalan, delivery note, pengiriman',
|
||||
'answer' => 'Surat jalan dipakai untuk mencatat barang yang dikirim atau pekerjaan yang dikirimkan ke pelanggan.',
|
||||
],
|
||||
[
|
||||
'keywords' => 'invoice, faktur, tagihan, pembayaran',
|
||||
'answer' => 'Invoice diterbitkan sebagai tagihan akhir setelah pengiriman barang atau penyelesaian jasa.',
|
||||
],
|
||||
];
|
||||
|
||||
$stmt = db()->prepare('INSERT INTO faqs (keywords, answer) VALUES (:keywords, :answer)');
|
||||
foreach ($seedFaqs as $faq) {
|
||||
$stmt->bindValue(':keywords', $faq['keywords']);
|
||||
$stmt->bindValue(':answer', $faq['answer']);
|
||||
$stmt->execute();
|
||||
}
|
||||
}
|
||||
|
||||
$bootstrapped = true;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user