diff --git a/SETUP.md b/SETUP.md new file mode 100644 index 0000000..177228f --- /dev/null +++ b/SETUP.md @@ -0,0 +1,113 @@ +# Project Setup Guide + +This guide provides step-by-step instructions to set up, configure, and run the Hospital Management System. + +## Prerequisites + +* **PHP**: Version 8.0 or higher. +* **Database**: MariaDB 10.x or MySQL 5.7+. +* **Web Server**: Apache 2.4+ (with `mod_rewrite` enabled). +* **Composer**: (Optional) For dependency management if using third-party packages in the future. + +## Installation Steps + +1. **Clone the Repository** + ```bash + git clone + cd + ``` + +2. **Configure Web Server** + * Point your Apache VirtualHost `DocumentRoot` to the project directory. + * Ensure the directory has appropriate permissions (e.g., `www-data` user). + * Enable `.htaccess` overrides if applicable. + +3. **Database Setup** + * Create a new MySQL/MariaDB database (e.g., `hospital_db`). + * Import the database schema and seed data. You can do this by running the initialization script or importing SQL files: + * **Option A (Script):** Run `php init_db.php` from the command line (ensure `db/config.php` is configured first). + * **Option B (Manual):** Import files from `db/migrations/` in chronological order using a tool like phpMyAdmin or CLI. + +4. **Configuration Files** + * **Database:** Edit `db/config.php` to match your database credentials: + ```php + define('DB_HOST', '127.0.0.1'); + define('DB_NAME', 'your_db_name'); + define('DB_USER', 'your_db_user'); + define('DB_PASS', 'your_db_password'); + ``` + +## Configuration & Environment Variables + +The application uses a mix of PHP constants and environment variables for configuration. + +### Email Configuration (`mail/config.php`) +The application uses PHPMailer. Configure the following environment variables (in your server config or `.env` file): + +* `MAIL_TRANSPORT`: `smtp` (default) +* `SMTP_HOST`: e.g., `smtp.gmail.com` +* `SMTP_PORT`: e.g., `587` +* `SMTP_SECURE`: `tls` or `ssl` +* `SMTP_USER`: Your email address +* `SMTP_PASS`: Your email password or App Password +* `MAIL_FROM`: Sender email address +* `MAIL_FROM_NAME`: Sender name (e.g., "Hospital Admin") + +### AI Integration (`ai/config.php`) +The system uses an AI proxy for features like "AI Suggestion" in visit forms and the Telegram bot. +* **Config File:** `ai/config.php` +* **Key Settings:** `base_url`, `project_uuid`. +* **Usage:** See `ai/LocalAIApi.php`. + +### Telegram Integration +The system includes a Telegram bot for answering FAQs (`api/telegram_webhook.php`). + +1. **Create a Bot:** Talk to `@BotFather` on Telegram to create a bot and get a **Token**. +2. **Save Token:** Insert the token into the `settings` table in your database: + ```sql + INSERT INTO settings (setting_key, setting_value) VALUES ('telegram_token', 'YOUR_TELEGRAM_BOT_TOKEN'); + ``` +3. **Set Webhook:** Configure the webhook URL for your bot: + ``` + https://api.telegram.org/bot/setWebhook?url=https:///api/telegram_webhook.php + ``` + +## Integrations & Libraries + +### Frontend (CDN) +The project relies on the following CDN-hosted libraries. Ensure you have an active internet connection. + +* **Framework:** Bootstrap 5.3.0 +* **Icons:** Bootstrap Icons 1.10.5 +* **Fonts:** Google Fonts (Inter, Tajawal) +* **Forms:** + * Select2 4.1.0 (with Bootstrap 5 theme) + * Summernote Lite 0.8.18 (Rich Text Editor) + * Flatpickr (Date/Time picker) + * Inputmask 5.0.7 (Input formatting) +* **Utilities:** + * jQuery 3.6.0 + * Ui-Avatars (User avatars) + * JsBarcode 3.11.5 (Patient labels) + +### Backend Services +* **Email:** `mail/MailService.php` (Wraps PHPMailer). +* **AI:** `ai/LocalAIApi.php` (Handles OpenAI requests via proxy). +* **Reporting:** `includes/SimpleXLSX.php` (Excel export support). + +## Default Credentials + +If you used the provided migration scripts (`20260321_create_auth_system.sql`), the default administrator account is: + +* **Email:** `admin@hospital.com` +* **Password:** `admin123` +* **Role:** Administrator + +**Note:** Change this password immediately after logging in. + +## Troubleshooting + +* **Database Connection Error:** Check `db/config.php` credentials. Ensure the database server is running. +* **Email Not Sending:** Verify SMTP settings in `mail/config.php` or environment variables. Check server logs for connection timeouts. +* **AI Features Not Working:** Ensure the server can reach the AI proxy endpoint defined in `ai/config.php`. +* **Telegram Bot Not Responding:** Verify the `telegram_token` in the `settings` table and ensure the webhook URL is accessible from the public internet (HTTPS required). diff --git a/apply_migrations.php b/apply_migrations.php index 007ed32..5cac112 100644 --- a/apply_migrations.php +++ b/apply_migrations.php @@ -1,5 +1,5 @@ setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true); diff --git a/db/config.php b/db/config.php index 54dcf71..7e73c63 100644 --- a/db/config.php +++ b/db/config.php @@ -1,17 +1,20 @@ PDO::ERRMODE_EXCEPTION, - PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, - ]); - } - return $pdo; -} +if (!function_exists('db')) { + function db() { + static $pdo; + if (!$pdo) { + $pdo = new PDO('mysql:host='.DB_HOST.';dbname='.DB_NAME.';charset=utf8mb4', DB_USER, DB_PASS, [ + PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => true, + ]); + } + return $pdo; + } +} \ No newline at end of file diff --git a/init_db.php b/init_db.php index e97c6ac..e8461c6 100644 --- a/init_db.php +++ b/init_db.php @@ -1,5 +1,5 @@ + + + + + + System Installation + + + + +
+
+
+

🏥 Hospital Management System Installer

+
+
+ "; + flush(); + } +} + +// Logic +$do_install = $is_cli || ($_SERVER['REQUEST_METHOD'] === 'POST'); + +if ($do_install) { + if (!$is_cli) { + echo '

Installation Progress

'; + } else { + echo "=== Hospital Management System Installer ===\n"; + } + + try { + // 1. Check Config + if (!file_exists(__DIR__ . '/db/config.php')) { + throw new Exception("Configuration file 'db/config.php' not found."); + } + log_msg("✅ Configuration file found.", $is_cli); + + require_once __DIR__ . '/db/config.php'; + $db = db(); + log_msg("✅ Database connection established.", $is_cli); + + // 2. Run init_db.php logic + log_msg("🔄 Initializing base database schema...", $is_cli); + + // Use output buffering to capture init_db output + ob_start(); + include __DIR__ . '/init_db.php'; + $init_output = ob_get_clean(); + + if ($is_cli) { + echo " >> " . str_replace("\n", "\n >> ", trim($init_output)) . "\n"; + } else { + log_msg(">> " . str_replace("\n", "
> ", trim($init_output)), $is_cli); + } + log_msg("✅ Base schema initialized.", $is_cli); + + // 3. Run migrations + log_msg("🔄 Applying migrations...", $is_cli); + + $files = glob(__DIR__ . '/db/migrations/*.sql'); + sort($files); + + $migrated_count = 0; + foreach ($files as $file) { + $filename = basename($file); + + $sql_content = file_get_contents($file); + $sql_content = preg_replace('/--.*$/m', '', $sql_content); + $statements = explode(';', $sql_content); + + foreach ($statements as $sql) { + $sql = trim($sql); + if (empty($sql)) continue; + + try { + // Use query() instead of exec() to handle potential result sets (like SELECT 1) + // and close the cursor explicitly. + $stmt = $db->query($sql); + if ($stmt) { + $stmt->closeCursor(); + } + } catch (PDOException $e) { + // Ignore "exists" errors + if (strpos($e->getMessage(), "Duplicate column") === false && + strpos($e->getMessage(), "already exists") === false && + strpos($e->getMessage(), "Duplicate key") === false && + strpos($e->getMessage(), "1062 Duplicate entry") === false) { + log_msg("⚠️ Error in $filename: " . $e->getMessage(), $is_cli); + } + } + } + $migrated_count++; + } + log_msg("✅ Applied $migrated_count migration files.", $is_cli); + + // 4. Verify Admin User + $stmt = $db->prepare("SELECT COUNT(*) FROM users WHERE email = ?"); + $stmt->execute(['admin@hospital.com']); + $count = $stmt->fetchColumn(); + $stmt->closeCursor(); // Close cursor + + if ($count == 0) { + log_msg("⚠️ Admin user missing. Creating...", $is_cli); + $pass = '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi'; // admin123 + // Ensure role 1 exists (Administrator) - seed roles first if missing + $stmt = $db->query("INSERT IGNORE INTO roles (id, name, slug, permissions) VALUES (1, 'Administrator', 'admin', '*')"); + $stmt->closeCursor(); + + $stmt = $db->query("INSERT INTO users (name, email, password, role_id) VALUES ('System Admin', 'admin@hospital.com', '$pass', 1)"); + $stmt->closeCursor(); + log_msg("✅ Admin user created.", $is_cli); + } else { + log_msg("✅ Admin user exists.", $is_cli); + } + + log_msg("🎉 Installation Completed Successfully!", $is_cli); + + if ($is_cli) { + echo "\nLogin Credentials:\n"; + echo "Email: admin@hospital.com\n"; + echo "Password: admin123\n"; + } + + } catch (Exception $e) { + log_msg("❌ CRITICAL ERROR: " . $e->getMessage(), $is_cli); + $error = true; + } + + if (!$is_cli) { + echo '
'; // End log-output + if (!isset($error)) { + echo '
+
Setup Complete!
+

You can now log in to the system.

+
    +
  • Email: admin@hospital.com
  • +
  • Password: admin123
  • +
+ Go to Dashboard +
'; + } else { + echo '
+
Setup Failed
+

Check logs above.

+ Retry +
'; + } + } + +} else { + // Web Mode: Show Welcome Screen + ?> +
Welcome
+

This script will set up the database tables and default data.

+ +
+ Prerequisites: +
    +
  • PHP Version:
  • +
  • Config File:
  • +
+
+ +
+ +
+ +
+ +
+
+ + + 'Filter', 'all_departments' => 'All Departments', 'total' => 'Total', + + // Dashboard & Common Missing Keys + 'total_patients' => 'Total Patients', + 'today_appointments' => 'Today\'s Appointments', + 'revenue' => 'Revenue', + 'pending' => 'Pending', + 'add_patient' => 'Add Patient', + 'book_appointment' => 'Book Appointment', + 'add_visit' => 'Add Visit', + 'add_xray_inquiry' => 'Add X-Ray Inquiry', + 'running_visits' => 'Running Visits', + 'time' => 'Time', + 'patient' => 'Patient', + 'doctor' => 'Doctor', + 'nurse' => 'Nurse', + 'checkout_payment' => 'Checkout Payment', + 'no_running_visits' => 'No running visits', + 'no_appointments_today' => 'No appointments today', + 'phone' => 'Phone', + 'not_insured' => 'Not Insured', + 'no_patients_found' => 'No patients found', + 'reason' => 'Reason', + 'new_visit' => 'New Visit', + 'select' => 'Select', + 'issue_token' => 'Issue Token', + 'select_service' => 'Select Service', + 'print_bill' => 'Print Bill', + 'close' => 'Close', + + // Login & Auth + 'fill_all_fields' => 'Please fill in all fields', + 'invalid_credentials' => 'Invalid email or password', + 'login_to_continue' => 'Login to continue to your account', + 'forgot_password' => 'Forgot Password?', ], 'ar' => [ 'dashboard' => 'لوحة التحكم', @@ -387,5 +421,39 @@ $translations = [ 'filter' => 'تصفية', 'all_departments' => 'كل الأقسام', 'total' => 'الإجمالي', + + // Dashboard & Common Missing Keys - Arabic + 'total_patients' => 'إجمالي المرضى', + 'today_appointments' => 'مواعيد اليوم', + 'revenue' => 'الإيرادات', + 'pending' => 'معلق', + 'add_patient' => 'إضافة مريض', + 'book_appointment' => 'حجز موعد', + 'add_visit' => 'إضافة زيارة', + 'add_xray_inquiry' => 'إضافة فحص أشعة', + 'running_visits' => 'الزيارات الجارية', + 'time' => 'الوقت', + 'patient' => 'المريض', + 'doctor' => 'الطبيب', + 'nurse' => 'الممرض', + 'checkout_payment' => 'دفع الحساب', + 'no_running_visits' => 'لا توجد زيارات جارية', + 'no_appointments_today' => 'لا توجد مواعيد اليوم', + 'phone' => 'الهاتف', + 'not_insured' => 'غير مؤمن', + 'no_patients_found' => 'لم يتم العثور على مرضى', + 'reason' => 'السبب', + 'new_visit' => 'زيارة جديدة', + 'select' => 'اختر', + 'issue_token' => 'إصدار تذكرة', + 'select_service' => 'اختر الخدمة', + 'print_bill' => 'طباعة الفاتورة', + 'close' => 'إغلاق', + + // Login & Auth + 'fill_all_fields' => 'يرجى ملء جميع الحقول', + 'invalid_credentials' => 'البريد الإلكتروني أو كلمة المرور غير صحيحة', + 'login_to_continue' => 'قم بتسجيل الدخول للمتابعة', + 'forgot_password' => 'هل نسيت كلمة المرور؟', ] ]; \ No newline at end of file