prepare("SELECT username, full_name, role, is_active FROM users WHERE id = ?"); $uStmt->execute([$userId]); $dbUser = $uStmt->fetch(PDO::FETCH_ASSOC); } catch (PDOException $e) { $dbUser = false; } if (!$dbUser || (int)($dbUser['is_active'] ?? 1) !== 1) { // Account removed or retired: end the session. $_SESSION = []; session_destroy(); header('Location: login.php'); exit; } $allowedDbRoles = ['Admin', 'Calling Admin', 'Operator Admin', 'Finance', 'Operator', 'Editor']; if (!in_array($dbUser['role'], $allowedDbRoles, true)) { $_SESSION = []; session_destroy(); header('Location: login.php'); exit; } // Role changed in the database -> drop any leftover Admin "view as" state. if (($_SESSION['role'] ?? '') !== $dbUser['role']) { unset($_SESSION['view_as'], $_SESSION['view_editor_id']); } $_SESSION['role'] = $dbUser['role']; $_SESSION['username'] = $dbUser['username']; $_SESSION['full_name'] = $dbUser['full_name']; $userRole = $dbUser['role']; $username = $dbUser['username']; // ── Calling Admin / Operator Admin ────────────────────────────────────────── // Both are limited admins. The rest of this page treats them as 'Admin' for // record access, and the flags below hide what they must not see. // Admin : everything // Calling Admin : all call records, Assign Editors, Editors Summary, view-as-editor // Operator Admin : Management (Operator) view of all confirmed records, Assign Operators $realRole = $userRole; $isFullAdmin = ($realRole === 'Admin'); $isCallingAdmin = ($realRole === 'Calling Admin'); $isOperatorAdmin = ($realRole === 'Operator Admin'); if ($isCallingAdmin || $isOperatorAdmin) { $userRole = 'Admin'; unset($_GET['view_as']); // they cannot switch views themselves if ($isCallingAdmin) { unset($_SESSION['view_as']); // never the Operator view } else { $_SESSION['view_as'] = 'Operator'; // always the Operator view unset($_SESSION['view_editor_id'], $_GET['view_editor_id']); } } // Internal Messages: unread count for the actual logged-in user. $internalUnreadCount = 0; try { $msgCountStmt = $pdo->prepare("SELECT COUNT(*) FROM internal_messages WHERE receiver_id = ? AND is_read = 0"); $msgCountStmt->execute([(int)$userId]); $internalUnreadCount = (int)$msgCountStmt->fetchColumn(); } catch (PDOException $e) { $internalUnreadCount = 0; } // Admin View-As logic (Persistent via Session) if ($userRole === 'Admin') { if (isset($_GET['view_as'])) { if ($_GET['view_as'] === 'Operator') { $_SESSION['view_as'] = 'Operator'; unset($_SESSION['view_editor_id']); } else { unset($_SESSION['view_as']); unset($_SESSION['view_editor_id']); } } if (isset($_GET['view_editor_id'])) { if ($_GET['view_editor_id'] !== '') { $_SESSION['view_editor_id'] = (int)$_GET['view_editor_id']; unset($_SESSION['view_as']); } else { unset($_SESSION['view_editor_id']); } } } $actualUserRole = $userRole; $viewAsOperator = ($actualUserRole === 'Admin' && ($_SESSION['view_as'] ?? '') === 'Operator'); $viewEditorId = ($actualUserRole === 'Admin') ? ($_SESSION['view_editor_id'] ?? '') : ''; $displayRole = $viewAsOperator ? 'Operator' : ($viewEditorId ? 'Editor' : $actualUserRole); $effectiveUserId = $viewEditorId ?: $userId; // New Arrivals -> Process: make sure the registered client has a Confirm inquiry // and an operator_process_details row, then open the operator processing page. if (isset($_GET['arrival_process']) && $displayRole === 'Operator') { $rcId = (int)$_GET['arrival_process']; try { $rcStmt = $pdo->prepare("SELECT * FROM registered_clients WHERE id = ?"); $rcStmt->execute([$rcId]); $rc = $rcStmt->fetch(PDO::FETCH_ASSOC); if ($rc) { $inqStmt = $pdo->prepare("SELECT id FROM inquiries WHERE phone_number = ? ORDER BY id DESC LIMIT 1"); $inqStmt->execute([$rc['phone_number']]); $inqId = (int)$inqStmt->fetchColumn(); $pdo->beginTransaction(); if (!$inqId) { $ins = $pdo->prepare("INSERT INTO inquiries (customer_name, phone_number, location_name, details, customer_category, status, operator_id, year, month, created_at, updated_at) VALUES (?, ?, ?, ?, ?, 'Confirm', ?, ?, ?, NOW(), NOW())"); $ins->execute([ $rc['customer_name'] ?: ($rc['name_with_initial'] ?? ''), $rc['phone_number'], $rc['location_name'] ?? '', $rc['details'] ?? '', $rc['customer_category'] ?? null, ($userRole === 'Operator') ? (int)$userId : null, (int)date('Y'), date('F'), ]); $inqId = (int)$pdo->lastInsertId(); } else { $pdo->prepare("UPDATE inquiries SET status = 'Confirm', operator_id = COALESCE(operator_id, ?), updated_at = NOW() WHERE id = ?") ->execute([($userRole === 'Operator') ? (int)$userId : null, $inqId]); } $chk = $pdo->prepare("SELECT COUNT(*) FROM operator_process_details WHERE inquiry_id = ?"); $chk->execute([$inqId]); if (!(int)$chk->fetchColumn()) { $pdo->prepare("INSERT INTO operator_process_details (inquiry_id, operator_stage) VALUES (?, 'Confirm')")->execute([$inqId]); } $pdo->commit(); header('Location: operator_edit.php?id=' . $inqId . '&return_url=' . urlencode('index.php?view_as=Operator')); exit; } } catch (PDOException $e) { if ($pdo->inTransaction()) $pdo->rollBack(); } } // Search & Filter $search = $_GET['search'] ?? ''; $category = $_GET['category'] ?? ''; $month = $_GET['month'] ?? ''; $selectedYear = $_GET['year'] ?? 'current'; $operator_stage = $_GET['operator_stage'] ?? ''; $payment_status = $_GET['payment_status'] ?? ''; $passport_status_filter = $_GET['passport_status'] ?? ''; $whereClauses = []; $params = []; // Apply year filter if ($selectedYear === 'current') { $whereClauses[] = "inquiries.year = ?"; $params[] = (int)date('Y'); } elseif ($selectedYear !== 'all') { $whereClauses[] = "inquiries.year = ?"; $params[] = (int)$selectedYear; } $isDefaultView = !isset($_GET['category']) && !isset($_GET['search']) && !isset($_GET['month']) && !isset($_GET['payment_status']) && !isset($_GET['operator_stage']) && !isset($_GET['year']) && !isset($_GET['passport_status']); if ($displayRole === 'Editor') { // Editor sees only their assigned calls $whereClauses[] = "inquiries.assigned_to = ?"; $params[] = $effectiveUserId; if ($isDefaultView) { $whereClauses[] = "(DATE(inquiries.created_at) = CURDATE() OR DATE(inquiries.updated_at) = CURDATE())"; } } elseif ($displayRole === 'Admin') { if ($isDefaultView) { $whereClauses[] = "(DATE(inquiries.created_at) >= DATE_SUB(CURDATE(), INTERVAL 2 DAY) OR DATE(inquiries.updated_at) >= DATE_SUB(CURDATE(), INTERVAL 2 DAY))"; } } elseif ($displayRole === 'Finance') { $whereClauses[] = "inquiries.status = 'Confirm'"; } elseif ($displayRole === 'Operator') { $whereClauses[] = "inquiries.status = 'Confirm'"; // Actual Operators only see their assignedConfirmed list // Admin viewing as Operator sees all confirmed (for oversight) if ($userRole === 'Operator') { $whereClauses[] = "inquiries.operator_id = ?"; $params[] = $userId; } } if ($category) { if ($category === 'WhatsApp') { $whereClauses[] = "inquiries.status IN ('No Answer', 'Not Reachable')"; } elseif ($category === 'Active') { $whereClauses[] = "inquiries.status IN ('New Calls', 'In Progress', 'Special Call')"; } elseif ($category === 'Confirmed') { $whereClauses[] = "inquiries.status = 'Confirm'"; } elseif ($category === 'Complete') { $whereClauses[] = "opd.operator_stage = 'Complete'"; } elseif ($category === 'Cancel') { $whereClauses[] = "inquiries.status = 'Cancel'"; } elseif ($category === 'RecentUpdates') { $whereClauses[] = "(DATE(inquiries.created_at) >= DATE_SUB(CURDATE(), INTERVAL 2 DAY) OR DATE(inquiries.updated_at) >= DATE_SUB(CURDATE(), INTERVAL 2 DAY) OR DATE(opd.updated_at) >= DATE_SUB(CURDATE(), INTERVAL 2 DAY))"; } elseif (in_array($category, ['Platinum', 'Gold', 'Silver'])) { $whereClauses[] = "inquiries.customer_category = ?"; $params[] = $category; } else { $whereClauses[] = "inquiries.status = ?"; $params[] = $category; } } if ($operator_stage) { if ($operator_stage === 'Confirm') { $whereClauses[] = "(inquiries.status = 'Confirm' OR opd.operator_stage IS NULL)"; } else { $whereClauses[] = "opd.operator_stage = ?"; $params[] = $operator_stage; } } if ($month) { $whereClauses[] = "inquiries.month = ?"; $params[] = $month; } if ($payment_status) { if ($payment_status === 'Full') { $whereClauses[] = "opd.is_balance_paid = 1"; } elseif ($payment_status === 'Advance') { $whereClauses[] = "(opd.is_balance_paid = 0 OR opd.is_balance_paid IS NULL) AND inquiries.advanced_payment > 0"; } elseif ($payment_status === 'Unpaid') { $whereClauses[] = "(opd.is_balance_paid = 0 OR opd.is_balance_paid IS NULL) AND (inquiries.advanced_payment = 0 OR inquiries.advanced_payment IS NULL)"; } } if ($passport_status_filter) { if ($passport_status_filter === 'No Passport') { $whereClauses[] = "(opd.passport_status IS NULL OR opd.passport_status NOT IN ('In Progress','Completed'))"; } else { $whereClauses[] = "opd.passport_status = ?"; $params[] = $passport_status_filter; } } if ($search) { $whereClauses[] = "(inquiries.id LIKE ? OR inquiries.customer_name LIKE ? OR inquiries.phone_number LIKE ? OR inquiries.location_name LIKE ? OR DATE_FORMAT(inquiries.created_at, '%Y-%m-%d') LIKE ?)"; $searchTerm = "%$search%"; $params[] = $searchTerm; $params[] = $searchTerm; $params[] = $searchTerm; $params[] = $searchTerm; $params[] = $searchTerm; } $whereSql = ''; if (count($whereClauses) > 0) { $whereSql = "WHERE " . implode(' AND ', $whereClauses); } // Pagination $perPage = 50; $page = max(1, (int)($_GET['page'] ?? 1)); $offset = ($page - 1) * $perPage; // Count total records for pagination $countStmt = $pdo->prepare("SELECT COUNT(*) FROM inquiries LEFT JOIN users ON inquiries.assigned_to = users.id LEFT JOIN operator_process_details opd ON inquiries.id = opd.inquiry_id $whereSql"); $countStmt->execute($params); $totalRecords = (int)$countStmt->fetchColumn(); $totalPages = max(1, (int)ceil($totalRecords / $perPage)); $page = min($page, $totalPages); $offset = ($page - 1) * $perPage; // Fetch inquiries (paginated) - also fetch payment fields // LIMIT and OFFSET must be cast to int and embedded directly — PDO binds them as strings which MariaDB rejects $orderBy = "inquiries.updated_at DESC"; if (!empty($category) || !empty($operator_stage) || !empty($search) || !empty($month) || !empty($payment_status) || $displayRole === 'Operator') { $orderBy = "inquiries.id DESC"; } $stmt = $pdo->prepare("SELECT inquiries.*, opd.operator_stage, opd.is_balance_paid, opd.passport_status, users.username as assigned_user, users.full_name as assigned_full_name FROM inquiries LEFT JOIN users ON inquiries.assigned_to = users.id LEFT JOIN operator_process_details opd ON inquiries.id = opd.inquiry_id $whereSql ORDER BY $orderBy LIMIT " . (int)$perPage . " OFFSET " . (int)$offset); $stmt->execute($params); $inquiries = $stmt->fetchAll(PDO::FETCH_ASSOC); // Fetch stats $statClauses = []; if ($displayRole === 'Editor') { $statClauses[] = "inquiries.assigned_to = " . (int)$effectiveUserId; } elseif ($displayRole === 'Finance') { $statClauses[] = "inquiries.status = 'Confirm'"; } elseif ($displayRole === 'Operator') { $statClauses[] = "inquiries.status = 'Confirm'"; if ($userRole === 'Operator') { $statClauses[] = "inquiries.operator_id = " . (int)$userId; } } if ($selectedYear === 'current') { $statClauses[] = "inquiries.year = " . (int)date('Y'); } elseif ($selectedYear !== 'all') { $statClauses[] = "inquiries.year = " . (int)$selectedYear; } $statWhere = count($statClauses) > 0 ? "WHERE " . implode(" AND ", $statClauses) : ""; $statStmt = $pdo->query("SELECT inquiries.status, COUNT(*) as count FROM inquiries LEFT JOIN operator_process_details opd ON inquiries.id = opd.inquiry_id $statWhere GROUP BY inquiries.status"); $statusCounts = $statStmt->fetchAll(PDO::FETCH_KEY_PAIR); // Operator specific stats $operatorStats = []; if ($displayRole === 'Operator') { $opWhereClauses = ["inquiries.status = 'Confirm'"]; if ($userRole === 'Operator') { $opWhereClauses[] = "inquiries.operator_id = " . (int)$userId; } if ($selectedYear === 'current') { $opWhereClauses[] = "inquiries.year = " . (int)date('Y'); } elseif ($selectedYear !== 'all') { $opWhereClauses[] = "inquiries.year = " . (int)$selectedYear; } $opWhereSql = "WHERE " . implode(" AND ", $opWhereClauses); $opStmt = $pdo->query("SELECT IFNULL(opd.operator_stage, 'Confirm') as stage, COUNT(*) as count FROM inquiries LEFT JOIN operator_process_details opd ON inquiries.id = opd.inquiry_id $opWhereSql GROUP BY stage"); $operatorStats = $opStmt->fetchAll(PDO::FETCH_KEY_PAIR); } // Passport status stats for Operator view $passportStats = ['In Progress' => 0, 'No Passport' => 0, 'Completed' => 0]; if ($displayRole === 'Operator') { $ppWhereClauses = ["inquiries.status = 'Confirm'"]; if ($userRole === 'Operator') { $ppWhereClauses[] = "inquiries.operator_id = " . (int)$userId; } if ($selectedYear === 'current') { $ppWhereClauses[] = "inquiries.year = " . (int)date('Y'); } elseif ($selectedYear !== 'all') { $ppWhereClauses[] = "inquiries.year = " . (int)$selectedYear; } $ppWhereSql = "WHERE " . implode(" AND ", $ppWhereClauses); $ppStmt = $pdo->query("SELECT IFNULL(opd.passport_status, 'No Passport') as ps, COUNT(*) as count FROM inquiries LEFT JOIN operator_process_details opd ON inquiries.id = opd.inquiry_id $ppWhereSql GROUP BY ps"); foreach ($ppStmt->fetchAll(PDO::FETCH_ASSOC) as $row) { $key = $row['ps']; if ($key === 'In Progress') $passportStats['In Progress'] = (int)$row['count']; elseif ($key === 'Completed') $passportStats['Completed'] = (int)$row['count']; else $passportStats['No Passport'] += (int)$row['count']; } } $monthlyConfirmedStats = []; if ($displayRole === 'Operator' || $displayRole === 'Admin' || $displayRole === 'Editor' || $displayRole === 'Finance') { $mq = "SELECT month, COUNT(*) as count FROM inquiries WHERE status = 'Confirm' AND month IS NOT NULL AND month != ''"; if ($userRole === 'Operator') { $mq .= " AND operator_id = " . (int)$userId; } elseif ($displayRole === 'Editor') { $mq .= " AND assigned_to = " . (int)$effectiveUserId; } if ($selectedYear === 'current') { $mq .= " AND year = " . (int)date('Y'); } elseif ($selectedYear !== 'all') { $mq .= " AND year = " . (int)$selectedYear; } $mq .= " GROUP BY month"; $monthStmt = $pdo->query($mq); $monthlyConfirmedStats = $monthStmt->fetchAll(PDO::FETCH_KEY_PAIR); } // Finance: amount received per month (keyed by month name e.g. "January") $monthlyAmountStats = []; if ($displayRole === 'Finance') { $maStmt = $pdo->query("SELECT MONTHNAME(i.payment_date) as mname, SUM(IF(opd.is_balance_paid = 1, i.total_payment - i.discount, i.advanced_payment)) as total FROM inquiries i LEFT JOIN operator_process_details opd ON i.id = opd.inquiry_id WHERE i.status = 'Confirm' AND i.payment_date IS NOT NULL " . ($selectedYear === 'current' ? "AND YEAR(i.payment_date) = " . (int)date('Y') : ($selectedYear !== 'all' ? "AND YEAR(i.payment_date) = " . (int)$selectedYear : "")) . " GROUP BY mname"); foreach ($maStmt->fetchAll(PDO::FETCH_ASSOC) as $row) { $monthlyAmountStats[$row['mname']] = (float)$row['total']; } } // Finance: expense per month (keyed by month name) $monthlyExpenseStats = []; if ($displayRole === 'Finance') { $meStmt = $pdo->query("SELECT MONTHNAME(expense_date) as mname, SUM(amount) as total FROM company_expenses WHERE 1=1 " . ($selectedYear === 'current' ? "AND YEAR(expense_date) = " . (int)date('Y') : ($selectedYear !== 'all' ? "AND YEAR(expense_date) = " . (int)$selectedYear : "")) . " GROUP BY mname"); foreach ($meStmt->fetchAll(PDO::FETCH_ASSOC) as $row) { $monthlyExpenseStats[$row['mname']] = (float)$row['total']; } } // Finance: selected-month detail (revenue, expenses, net) when a month filter is active $selectedMonthRevenue = 0; $selectedMonthExpenses = 0; if ($displayRole === 'Finance' && $month) { $smrStmt = $pdo->prepare("SELECT SUM(IF(opd.is_balance_paid = 1, i.total_payment - i.discount, i.advanced_payment)) as total FROM inquiries i LEFT JOIN operator_process_details opd ON i.id = opd.inquiry_id WHERE i.status = 'Confirm' AND i.payment_date IS NOT NULL AND MONTHNAME(i.payment_date) = ? " . ($selectedYear === 'current' ? "AND YEAR(i.payment_date) = " . (int)date('Y') : ($selectedYear !== 'all' ? "AND YEAR(i.payment_date) = " . (int)$selectedYear : ""))); $smrStmt->execute([$month]); $selectedMonthRevenue = (float)$smrStmt->fetchColumn() ?: 0; $smeStmt = $pdo->prepare("SELECT SUM(amount) FROM company_expenses WHERE MONTHNAME(expense_date) = ? " . ($selectedYear === 'current' ? "AND YEAR(expense_date) = " . (int)date('Y') : ($selectedYear !== 'all' ? "AND YEAR(expense_date) = " . (int)$selectedYear : ""))); $smeStmt->execute([$month]); $selectedMonthExpenses = (float)$smeStmt->fetchColumn() ?: 0; } // Overall totals for Finance $overallRevenue = 0; $overallExpenses = 0; if ($displayRole === 'Finance') { $ovrStmt = $pdo->query("SELECT SUM(IF(opd.is_balance_paid = 1, i.total_payment - i.discount, i.advanced_payment)) as total FROM inquiries i LEFT JOIN operator_process_details opd ON i.id = opd.inquiry_id WHERE i.status = 'Confirm' AND i.payment_date IS NOT NULL " . ($selectedYear === 'current' ? "AND YEAR(i.payment_date) = " . (int)date('Y') : ($selectedYear !== 'all' ? "AND YEAR(i.payment_date) = " . (int)$selectedYear : ""))); $overallRevenue = (float)$ovrStmt->fetchColumn() ?: 0; $oveStmt = $pdo->query("SELECT SUM(amount) FROM company_expenses WHERE 1=1 " . ($selectedYear === 'current' ? "AND YEAR(expense_date) = " . (int)date('Y') : ($selectedYear !== 'all' ? "AND YEAR(expense_date) = " . (int)$selectedYear : ""))); $overallExpenses = (float)$oveStmt->fetchColumn() ?: 0; } // Fetch complete count (operator_stage = 'Complete' in operator_process_details) $completeCountClause = " WHERE opd.operator_stage = 'Complete'"; if ($displayRole === 'Editor') { $completeCountClause .= " AND i.assigned_to = " . (int)$effectiveUserId; } elseif ($userRole === 'Operator') { $completeCountClause .= " AND i.operator_id = " . (int)$userId; } if ($selectedYear === 'current') { $completeCountClause .= " AND i.year = " . (int)date('Y'); } elseif ($selectedYear !== 'all') { $completeCountClause .= " AND i.year = " . (int)$selectedYear; } $completeStmt = $pdo->query("SELECT COUNT(*) FROM inquiries i INNER JOIN operator_process_details opd ON i.id = opd.inquiry_id" . $completeCountClause); $completeCount = (int)$completeStmt->fetchColumn(); $recentWhere = $statWhere ? $statWhere . " AND " : "WHERE "; $recentWhere .= "(DATE(inquiries.created_at) >= DATE_SUB(CURDATE(), INTERVAL 2 DAY) OR DATE(inquiries.updated_at) >= DATE_SUB(CURDATE(), INTERVAL 2 DAY) OR DATE(opd.updated_at) >= DATE_SUB(CURDATE(), INTERVAL 2 DAY))"; $recentStmt = $pdo->query("SELECT COUNT(*) FROM inquiries LEFT JOIN operator_process_details opd ON inquiries.id = opd.inquiry_id $recentWhere"); $recentUpdatesCount = (int)$recentStmt->fetchColumn(); $stats = [ 'total' => array_sum($statusCounts ?: []), 'recent_updates' => $recentUpdatesCount, 'new_calls' => ($statusCounts['New Calls'] ?? 0), 'no_answer' => ($statusCounts['No Answer'] ?? 0), 'unreachable' => ($statusCounts['Not Reachable'] ?? 0), 'in_progress' => ($statusCounts['In Progress'] ?? 0), 'special_call' => ($statusCounts['Special Call'] ?? 0), 'confirm' => max(0, ($statusCounts['Confirm'] ?? 0) - ($userRole === 'Operator' || $displayRole === 'Operator' ? ($operatorStats['Complete'] ?? 0) : $completeCount)), 'complete' => ($userRole === 'Operator' || $displayRole === 'Operator') ? ($operatorStats['Complete'] ?? 0) : $completeCount, 'cancel' => ($statusCounts['Cancel'] ?? 0), ]; $monthColors = [ 'January' => '#3498db', 'February' => '#9b59b6', 'March' => '#e67e22', 'April' => '#27ae60', 'May' => '#e74c3c', 'June' => '#1abc9c', 'July' => '#f1c40f', 'August' => '#34495e', 'September' => '#d35400', 'October' => '#7f8c8d', 'November' => '#2980b9', 'December' => '#2c3e50' ]; // Finance specific stats (Amounts received) $dailyTotals = []; $monthlyTotals = []; if ($displayRole === 'Finance') { $finYearCondition = ""; if ($selectedYear === 'current') { $finYearCondition = " AND YEAR(i.payment_date) = " . (int)date('Y'); } elseif ($selectedYear !== 'all') { $finYearCondition = " AND YEAR(i.payment_date) = " . (int)$selectedYear; } $dailyStmt = $pdo->query("SELECT i.payment_date as p_date, SUM(IF(opd.is_balance_paid = 1, i.total_payment - i.discount, i.advanced_payment)) as total FROM inquiries i LEFT JOIN operator_process_details opd ON i.id = opd.inquiry_id WHERE i.status = 'Confirm' AND i.payment_date IS NOT NULL $finYearCondition GROUP BY i.payment_date ORDER BY i.payment_date DESC LIMIT 10"); $dailyTotals = $dailyStmt->fetchAll(PDO::FETCH_ASSOC); $monthlyStmt = $pdo->query("SELECT DATE_FORMAT(i.payment_date, '%Y-%m') as p_month, SUM(IF(opd.is_balance_paid = 1, i.total_payment - i.discount, i.advanced_payment)) as total FROM inquiries i LEFT JOIN operator_process_details opd ON i.id = opd.inquiry_id WHERE i.status = 'Confirm' AND i.payment_date IS NOT NULL $finYearCondition GROUP BY p_month ORDER BY p_month DESC LIMIT 12"); $monthlyTotals = $monthlyStmt->fetchAll(PDO::FETCH_ASSOC); } // Fetch Payment Status stats for the confirmed view $payStats = ['Full' => 0, 'Advance' => 0, 'Unpaid' => 0]; if ($displayRole === 'Operator' || $displayRole === 'Admin' || $displayRole === 'Editor') { $payWhereClauses = []; $payParams = []; // Base filters (Role/Year) if ($displayRole === 'Editor') { $payWhereClauses[] = "inquiries.assigned_to = ?"; $payParams[] = $effectiveUserId; } elseif ($displayRole === 'Operator') { if ($userRole === 'Operator') { $payWhereClauses[] = "inquiries.operator_id = ?"; $payParams[] = $userId; } } if ($selectedYear === 'current') { $payWhereClauses[] = "inquiries.year = ?"; $payParams[] = (int)date('Y'); } elseif ($selectedYear !== 'all') { $payWhereClauses[] = "inquiries.year = ?"; $payParams[] = (int)$selectedYear; } if ($month) { $payWhereClauses[] = "inquiries.month = ?"; $payParams[] = $month; } $payWhereClauses[] = "inquiries.status = 'Confirm'"; $payWhereSql = "WHERE " . implode(' AND ', $payWhereClauses); $payQuery = "SELECT SUM(CASE WHEN opd.is_balance_paid = 1 THEN 1 ELSE 0 END) as full_paid, SUM(CASE WHEN (opd.is_balance_paid = 0 OR opd.is_balance_paid IS NULL) AND inquiries.advanced_payment > 0 THEN 1 ELSE 0 END) as advance_paid, SUM(CASE WHEN (opd.is_balance_paid = 0 OR opd.is_balance_paid IS NULL) AND (inquiries.advanced_payment = 0 OR inquiries.advanced_payment IS NULL) THEN 1 ELSE 0 END) as unpaid FROM inquiries LEFT JOIN operator_process_details opd ON inquiries.id = opd.inquiry_id $payWhereSql"; $payStmt = $pdo->prepare($payQuery); $payStmt->execute($payParams); $payRow = $payStmt->fetch(PDO::FETCH_ASSOC); if ($payRow) { $payStats['Full'] = (int)$payRow['full_paid']; $payStats['Advance'] = (int)$payRow['advance_paid']; $payStats['Unpaid'] = (int)$payRow['unpaid']; } } // New Arrivals (Operator view): clients registered via registered_create.php in the last 7 days $newArrivalsCount = 0; $newArrivals = []; if ($displayRole === 'Operator') { try { $newArrivalsCount = (int)$pdo->query("SELECT COUNT(*) FROM registered_clients WHERE created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY)")->fetchColumn(); $newArrivals = $pdo->query("SELECT rc.*, u.username, u.full_name, inq.id AS inquiry_id, inq.status AS inq_status, inq.advanced_payment, inq.id_card_number, opd.operator_stage, opd.is_balance_paid, opd.passport_status FROM registered_clients rc LEFT JOIN users u ON rc.registered_by = u.id LEFT JOIN inquiries inq ON inq.id = (SELECT MAX(i2.id) FROM inquiries i2 WHERE i2.phone_number = rc.phone_number) LEFT JOIN operator_process_details opd ON opd.inquiry_id = inq.id WHERE rc.created_at >= DATE_SUB(NOW(), INTERVAL 7 DAY) ORDER BY rc.created_at DESC LIMIT 100")->fetchAll(PDO::FETCH_ASSOC); } catch (PDOException $e) { // Table not created yet (no one has opened Registered Clients) - show 0 $newArrivalsCount = 0; $newArrivals = []; } } function getBadgeClass($status) { switch($status) { case 'No Answer': case 'Not Reachable': return 'badge-missed'; case 'New Calls': return 'badge-new'; case 'In Progress': return 'badge-progress'; case 'Special Call': return 'badge-special'; case 'Confirm': return 'badge-booked'; case 'Complete': return 'badge-complete'; case 'Cancel': return 'badge-cancel'; default: return 'badge-new'; } } function managementAssignmentBadge(array $row): array { if (empty($row['operator_id'])) { return ['Unassigned', 'management-unassigned']; } if (($row['operator_stage'] ?? '') === 'Complete') { return ['Completed', 'management-complete']; } if (empty($row['management_acknowledged_at'])) { return ['Newly Assigned', 'management-new']; } return ['Accepted / In Progress', 'management-accepted']; } ?> Thinulaka Tours | Dashboard
prepare("SELECT full_name, username FROM users WHERE id = ?"); $edStmt->execute([$viewEditorId]); $edUser = $edStmt->fetch(); if ($edUser) { $displaySuffix = " › Editor: " . htmlspecialchars($edUser['full_name'] ?: $edUser['username']); } } ?>

Dashboard (: )

Total ()
New Arrivals
Confirm
In Progress
Passport Process
Visa Process
Baggage
Payment Process
Return
Total
New Calls
In Progress
No Answer CSV
WhatsApp CSV
> Confirm
Complete
Special Call CSV
Cancel
Clear
1, 'February'=>2, 'March'=>3, 'April'=>4, 'May'=>5, 'June'=>6, 'July'=>7, 'August'=>8, 'September'=>9, 'October'=>10, 'November'=>11, 'December'=>12 ]; $currentYear = (int)date('Y'); $currentMonthNum = (int)date('n'); $compareYear = ($selectedYear === 'current' || $selectedYear === 'all') ? $currentYear : (int)$selectedYear; $hasPastMonths = false; $initiallyShown = false; $allMonths = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"]; foreach ($allMonths as $m) { $mNum = $monthNumbers[$m]; $isPast = false; if ($compareYear < $currentYear) { $isPast = true; } elseif ($compareYear > $currentYear) { $isPast = false; } else { $isPast = ($mNum < $currentMonthNum); } if ($isPast) { $hasPastMonths = true; if ($month === $m) { $initiallyShown = true; } } } ?>

Confirmed List by Assigned Month

$currentYear) { $isPast = false; } else { $isPast = ($mNum < $currentMonthNum); } ?>
0): ?>
k
0): ?>
k
0): ?>

— Financial Breakdown

Revenue
LKR
Expenses
LKR
Net = 0 ? 'Profit' : 'Loss' ?>
LKR

Overall —

Total Revenue
LKR
Total Expenses
LKR
Net = 0 ? 'Profit' : 'Loss' ?>
LKR

Financial Summary (Customer Payments Received)

Daily Breakdown (Last 10 Days)

Payment Date Amount Received (LKR)
No payment dates recorded.

Monthly Breakdown (Last 12 Months)

Month Amount Received (LKR)
No payment dates recorded.

All Inquiry Records

· Showing – of

Recent Updates
>
ID Payment Inquiry Details Name Phone Address Date / Month Status Management Assigned Actions
No records found.
Full Paid 0): ?> Advanced Unpaid Passport ✓ Passport… No Pass.
Showing – of records  |  Page of
1): ?>

Assign ID Number

Please enter the card number for this customer.