diff --git a/api/patients.php b/api/patients.php index 6674cc6..e7e5379 100644 --- a/api/patients.php +++ b/api/patients.php @@ -9,20 +9,36 @@ try { switch ($action) { case 'search': $q = $_GET['q'] ?? ''; - // Allow empty search to return nothing or some default? - // Select2 usually sends a query. + if (empty($q)) { - echo json_encode([]); + echo json_encode(['results' => []]); exit; } - // Search by name or phone - $sql = "SELECT id, name_en as name, phone FROM patients WHERE name_en LIKE ? OR name_ar LIKE ? OR phone LIKE ? LIMIT 20"; + // Search by name, phone or id (patient number) + $sql = "SELECT id, name, phone, civil_id FROM patients WHERE name LIKE ? OR phone LIKE ? OR civil_id LIKE ? OR id = ? LIMIT 20"; $stmt = $pdo->prepare($sql); $term = "%$q%"; - $stmt->execute([$term, $term, $term]); + $id_term = intval($q); // for exact match on patient number + $stmt->execute([$term, $term, $term, $id_term]); $results = $stmt->fetchAll(PDO::FETCH_ASSOC); - echo json_encode($results); + + // Format results for select2 + $formatted_results = array_map(function($p) { + $patient_number = sprintf('%06d', $p['id']); + $display_text = $patient_number . ' - ' . $p['name']; + if (!empty($p['phone'])) { + $display_text .= ' - ' . $p['phone']; + } + return [ + 'id' => $p['id'], + 'text' => $display_text, + 'name' => $p['name'], + 'phone' => $p['phone'] + ]; + }, $results); + + echo json_encode(['results' => $formatted_results]); break; default: @@ -32,4 +48,4 @@ try { } catch (Exception $e) { http_response_code(500); echo json_encode(['error' => $e->getMessage()]); -} \ No newline at end of file +} diff --git a/api/queue.php b/api/queue.php index 9b350a0..d96334a 100644 --- a/api/queue.php +++ b/api/queue.php @@ -74,7 +74,7 @@ try { } $sql = " - SELECT q.*, + SELECT q.*, td.name_$lang as target_department_name, p.name as patient_name, d.name_$lang as doctor_name, d.name_en as doctor_name_en, @@ -86,6 +86,7 @@ try { FROM patient_queue q JOIN patients p ON q.patient_id = p.id JOIN departments dept ON q.department_id = dept.id + LEFT JOIN departments td ON q.target_department_id = td.id LEFT JOIN employees d ON q.doctor_id = d.id $where ORDER BY @@ -138,6 +139,57 @@ try { exit; } + + // --- TRANSFER TOKEN --- + if ($action === 'transfer') { + if ($_SERVER['REQUEST_METHOD'] !== 'POST') { + throw new Exception('Invalid request method'); + } + + $queue_id = $_POST['queue_id'] ?? null; + $new_department_id = $_POST['department_id'] ?? null; + $new_doctor_id = $_POST['doctor_id'] ?? null; + + if (!$queue_id || !$new_department_id) { + throw new Exception('Queue ID and Target Department are required'); + } + + // Get current queue token + $stmt = $db->prepare("SELECT patient_id FROM patient_queue WHERE id = ?"); + $stmt->execute([$queue_id]); + $current = $stmt->fetch(PDO::FETCH_ASSOC); + + if (!$current) { + throw new Exception('Queue token not found'); + } + + // Complete the old token + $stmt = $db->prepare("UPDATE patient_queue SET status = 'completed', updated_at = NOW() WHERE id = ?"); + $stmt->execute([$queue_id]); + + // Create new token + $today = date('Y-m-d'); + $stmt = $db->prepare(" + SELECT MAX(token_number) + FROM patient_queue + WHERE department_id = ? + AND DATE(created_at) = ? + "); + $stmt->execute([$new_department_id, $today]); + $max_token = $stmt->fetchColumn(); + $next_token = ($max_token) ? $max_token + 1 : 1; + + $stmt = $db->prepare(" + INSERT INTO patient_queue (patient_id, department_id, doctor_id, token_number, status, created_at) + VALUES (?, ?, ?, ?, 'waiting', NOW()) + "); + $stmt->execute([$current['patient_id'], $new_department_id, $new_doctor_id ?: null, $next_token]); + $new_queue_id = $db->lastInsertId(); + + echo json_encode(['success' => true, 'message' => 'Token transferred', 'token_number' => $next_token, 'new_queue_id' => $new_queue_id]); + exit; + } + // --- SUMMARY --- if ($action === 'summary') { $today = date('Y-m-d'); @@ -160,6 +212,7 @@ try { SUM(CASE WHEN q.status = 'completed' THEN 1 ELSE 0 END) as completed FROM patient_queue q JOIN departments dept ON q.department_id = dept.id + LEFT JOIN departments td ON q.target_department_id = td.id $where GROUP BY dept.id "; diff --git a/db/migrations/20260328_add_smart_queue_routing.sql b/db/migrations/20260328_add_smart_queue_routing.sql new file mode 100644 index 0000000..1df7cbd --- /dev/null +++ b/db/migrations/20260328_add_smart_queue_routing.sql @@ -0,0 +1,3 @@ +ALTER TABLE departments ADD COLUMN requires_vitals TINYINT(1) DEFAULT 0; +ALTER TABLE departments ADD COLUMN is_vitals_room TINYINT(1) DEFAULT 0; +ALTER TABLE patient_queue ADD COLUMN target_department_id INT(11) DEFAULT NULL; diff --git a/fix_db.php b/fix_db.php deleted file mode 100644 index 232c191..0000000 --- a/fix_db.php +++ /dev/null @@ -1,77 +0,0 @@ -Applying Database Fixes..."; - -try { - // 1. Add columns if missing - try { - $db->exec("ALTER TABLE appointments ADD COLUMN start_time DATETIME NULL"); - echo "Added start_time column.
"; - } catch (PDOException $e) { - echo "start_time check: " . $e->getMessage() . "
"; - } - - try { - $db->exec("ALTER TABLE appointments ADD COLUMN end_time DATETIME NULL"); - echo "Added end_time column.
"; - } catch (PDOException $e) { - echo "end_time check: " . $e->getMessage() . "
"; - } - - // 2. Migrate data - // Check if appointment_date exists before trying to use it - try { - $stmt = $db->query("SHOW COLUMNS FROM appointments LIKE 'appointment_date'"); - if ($stmt->fetch()) { - $db->exec("UPDATE appointments SET start_time = appointment_date WHERE start_time IS NULL"); - echo "Migrated data from appointment_date to start_time.
"; - } else { - echo "Column 'appointment_date' does not exist, skipping data migration.
"; - } - } catch (PDOException $e) { - echo "Data migration check failed: " . $e->getMessage() . "
"; - } - - // Populate end_time based on start_time - try { - $db->exec("UPDATE appointments SET end_time = DATE_ADD(start_time, INTERVAL 30 MINUTE) WHERE end_time IS NULL AND start_time IS NOT NULL"); - echo "Populated end_time based on start_time.
"; - } catch (PDOException $e) { - echo "Could not populate end_time: " . $e->getMessage() . "
"; - } - - // 3. Set NOT NULL constraint - try { - // Only if start_time has values (or table is empty) - $db->exec("ALTER TABLE appointments MODIFY COLUMN start_time DATETIME NOT NULL"); - echo "Set start_time to NOT NULL.
"; - } catch (PDOException $e) { - echo "Could not set start_time to NOT NULL (maybe some rows are NULL?): " . $e->getMessage() . "
"; - } - - try { - $db->exec("ALTER TABLE appointments MODIFY COLUMN end_time DATETIME NOT NULL"); - echo "Set end_time to NOT NULL.
"; - } catch (PDOException $e) { - echo "Could not set end_time to NOT NULL: " . $e->getMessage() . "
"; - } - - // 4. Ensure other columns exist (like nurse_id, visit_type, etc. from previous migrations) - try { - $db->exec("ALTER TABLE appointments ADD COLUMN nurse_id INT NULL"); - } catch (Exception $e) {} - try { - $db->exec("ALTER TABLE appointments ADD COLUMN visit_type ENUM('Clinic', 'Home') DEFAULT 'Clinic'"); - } catch (Exception $e) {} - try { - $db->exec("ALTER TABLE appointments ADD COLUMN address TEXT NULL"); - } catch (Exception $e) {} - - echo "

Fix completed successfully.

"; - echo "

Go to Dashboard

"; - -} catch (PDOException $e) { - echo "

Fatal Error during fix:

" . $e->getMessage(); -} diff --git a/includes/actions.php b/includes/actions.php index 54b1073..9ac1d25 100644 --- a/includes/actions.php +++ b/includes/actions.php @@ -152,9 +152,11 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') $name_ar = $_POST['name_ar'] ?? ''; $show_in_queue = isset($_POST['show_in_queue']) ? 1 : 0; $active = isset($_POST['active']) ? 1 : 0; + $requires_vitals = isset($_POST['requires_vitals']) ? 1 : 0; + $is_vitals_room = isset($_POST['is_vitals_room']) ? 1 : 0; if ($name_en && $name_ar) { - $stmt = $db->prepare("INSERT INTO departments (name_en, name_ar, show_in_queue, active) VALUES (?, ?, ?, ?)"); - $stmt->execute([$name_en, $name_ar, $show_in_queue, $active]); + $stmt = $db->prepare("INSERT INTO departments (name_en, name_ar, show_in_queue, active, requires_vitals, is_vitals_room) VALUES (?, ?, ?, ?, ?, ?)"); + $stmt->execute([$name_en, $name_ar, $show_in_queue, $active, $requires_vitals, $is_vitals_room]); $_SESSION['flash_message'] = __('add_department') . ' ' . __('successfully'); $redirect = true; } @@ -164,9 +166,11 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') $name_ar = $_POST['name_ar'] ?? ''; $show_in_queue = isset($_POST['show_in_queue']) ? 1 : 0; $active = isset($_POST['active']) ? 1 : 0; + $requires_vitals = isset($_POST['requires_vitals']) ? 1 : 0; + $is_vitals_room = isset($_POST['is_vitals_room']) ? 1 : 0; if ($id && $name_en && $name_ar) { - $stmt = $db->prepare("UPDATE departments SET name_en = ?, name_ar = ?, show_in_queue = ?, active = ? WHERE id = ?"); - $stmt->execute([$name_en, $name_ar, $show_in_queue, $active, $id]); + $stmt = $db->prepare("UPDATE departments SET name_en = ?, name_ar = ?, show_in_queue = ?, active = ?, requires_vitals = ?, is_vitals_room = ? WHERE id = ?"); + $stmt->execute([$name_en, $name_ar, $show_in_queue, $active, $requires_vitals, $is_vitals_room, $id]); $_SESSION['flash_message'] = __('edit_department') . ' ' . __('successfully'); $redirect = true; } @@ -267,6 +271,8 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') $stmtQueue = $db->prepare("INSERT INTO patient_queue (patient_id, department_id, doctor_id, visit_id, token_number, status, created_at) VALUES (?, ?, ?, ?, ?, 'waiting', NOW())"); $stmtQueue->execute([$patient_id, $dept_id, $doctor_id, $visit_id, $next_token]); + $queue_id = $db->lastInsertId(); + $_SESSION['print_token_id'] = $queue_id; $token_message = " (" . __('token') . ": #" . $next_token . ")"; } @@ -1068,6 +1074,8 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') $text_en = $_POST['text_en'] ?? ''; $text_ar = $_POST['text_ar'] ?? ''; $active = isset($_POST['active']) ? 1 : 0; + $requires_vitals = isset($_POST['requires_vitals']) ? 1 : 0; + $is_vitals_room = isset($_POST['is_vitals_room']) ? 1 : 0; if ($text_en && $text_ar) { $stmt = $db->prepare("INSERT INTO queue_ads (text_en, text_ar, active) VALUES (?, ?, ?)"); @@ -1080,6 +1088,8 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') $text_en = $_POST['text_en'] ?? ''; $text_ar = $_POST['text_ar'] ?? ''; $active = isset($_POST['active']) ? 1 : 0; + $requires_vitals = isset($_POST['requires_vitals']) ? 1 : 0; + $is_vitals_room = isset($_POST['is_vitals_room']) ? 1 : 0; if ($id && $text_en && $text_ar) { $stmt = $db->prepare("UPDATE queue_ads SET text_en = ?, text_ar, active = ? WHERE id = ?"); @@ -1175,6 +1185,8 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') $password = password_hash($_POST['password'], PASSWORD_DEFAULT); $role_id = $_POST['role_id']; $active = isset($_POST['active']) ? 1 : 0; + $requires_vitals = isset($_POST['requires_vitals']) ? 1 : 0; + $is_vitals_room = isset($_POST['is_vitals_room']) ? 1 : 0; $stmt = $db->prepare("INSERT INTO users (name, email, password, role_id, active) VALUES (?, ?, ?, ?, ?)"); $stmt->execute([$name, $email, $password, $role_id, $active]); @@ -1191,6 +1203,8 @@ if (isset($_SERVER['REQUEST_METHOD']) && $_SERVER['REQUEST_METHOD'] === 'POST') $email = $_POST['email']; $role_id = $_POST['role_id']; $active = isset($_POST['active']) ? 1 : 0; + $requires_vitals = isset($_POST['requires_vitals']) ? 1 : 0; + $is_vitals_room = isset($_POST['is_vitals_room']) ? 1 : 0; $sql = "UPDATE users SET name = ?, email = ?, role_id = ?, active = ? WHERE id = ?"; $params = [$name, $email, $role_id, $active, $id]; diff --git a/includes/layout/footer.php b/includes/layout/footer.php index 464eec2..8ae6a24 100644 --- a/includes/layout/footer.php +++ b/includes/layout/footer.php @@ -20,7 +20,7 @@ @@ -744,7 +744,7 @@ @@ -1615,4 +1615,10 @@ $(document).ready(function() { }); }); + \ No newline at end of file diff --git a/includes/pages/appointments.php b/includes/pages/appointments.php index 27a1786..b4f6e81 100644 --- a/includes/pages/appointments.php +++ b/includes/pages/appointments.php @@ -75,7 +75,7 @@ diff --git a/includes/pages/dashboard.php b/includes/pages/dashboard.php index 5c021d4..1b386a1 100644 --- a/includes/pages/dashboard.php +++ b/includes/pages/dashboard.php @@ -344,7 +344,7 @@ $appointments = $db->query($appointments_sql)->fetchAll(); @@ -444,7 +444,7 @@ $appointments = $db->query($appointments_sql)->fetchAll(); diff --git a/includes/pages/departments.php b/includes/pages/departments.php index 469ea59..edf2087 100644 --- a/includes/pages/departments.php +++ b/includes/pages/departments.php @@ -308,6 +308,14 @@ if (isset($_GET['ajax_search'])) { +
+ + +
+
+ + +
+ + +