db = $db; $this->adminNotificationSubjectModel = $adminNotificationSubjectModel; } public function alertsPage(): array { $admins = $this->eligibleUsers(); $subjects = $this->subjectOptions(); $assignedSubjects = []; $tableReady = $this->db->tableExists('admin_notification_subjects'); if ($tableReady && !empty($admins)) { $adminIds = array_map('intval', array_column($admins, 'id')); $rows = $this->adminNotificationSubjectModel ->select('id, admin_id, subject') ->whereIn('admin_id', $adminIds) ->findAll(); foreach ($rows as $row) { $adminId = (int) ($row['admin_id'] ?? 0); $subject = (string) ($row['subject'] ?? ''); if ($adminId <= 0 || $subject === '') { continue; } if (!isset($assignedSubjects[$adminId])) { $assignedSubjects[$adminId] = []; } $assignedSubjects[$adminId][$subject] = true; } } return [ 'admins' => $admins, 'subjects' => $subjects, 'assignedSubjects' => $assignedSubjects, 'tableReady' => $tableReady, ]; } public function saveSubjects($posted): array { if (!$this->db->tableExists('admin_notification_subjects')) { return ['type' => 'error', 'message' => 'Notification subject storage is missing. Run migrations first.']; } if (!is_array($posted)) { return ['type' => 'error', 'message' => 'No selections were submitted.']; } $subjects = $this->subjectOptions(); $allowed = array_keys($subjects); $admins = $this->eligibleUsers(); $adminIds = array_map('intval', array_column($admins, 'id')); if (empty($adminIds)) { return ['type' => 'info', 'message' => 'No admins found to update.']; } $existing = $this->adminNotificationSubjectModel ->select('id, admin_id, subject') ->whereIn('admin_id', $adminIds) ->findAll(); $existingMap = []; foreach ($existing as $row) { $adminId = (int) ($row['admin_id'] ?? 0); $subject = (string) ($row['subject'] ?? ''); if ($adminId <= 0 || $subject === '') { continue; } if (!isset($existingMap[$adminId])) { $existingMap[$adminId] = []; } $existingMap[$adminId][$subject] = (int) ($row['id'] ?? 0); } $updates = 0; foreach ($adminIds as $adminId) { $subjectRaw = $posted[$adminId] ?? []; $selected = []; if (is_array($subjectRaw)) { foreach ($subjectRaw as $key => $value) { $candidate = is_string($key) ? $key : $value; if (!is_string($candidate)) { continue; } $candidate = trim($candidate); if ($candidate !== '') { $selected[] = $candidate; } } } $selected = array_values(array_unique(array_filter($selected, function ($value) use ($allowed) { return in_array($value, $allowed, true); }))); $current = array_keys($existingMap[$adminId] ?? []); $toDelete = array_values(array_diff($current, $selected)); $toInsert = array_values(array_diff($selected, $current)); if (!empty($toDelete)) { $this->adminNotificationSubjectModel ->where('admin_id', $adminId) ->whereIn('subject', $toDelete) ->delete(); $updates += count($toDelete); } if (!empty($toInsert)) { $batch = []; foreach ($toInsert as $subject) { $batch[] = [ 'admin_id' => $adminId, 'subject' => $subject, ]; } $this->adminNotificationSubjectModel->insertBatch($batch); $updates += count($toInsert); } } return ['type' => 'success', 'message' => $updates > 0 ? 'Notification subjects updated.' : 'No changes were made.']; } public function printRecipientsPage(): array { $admins = $this->eligibleUsers(); $tableReady = $this->db->tableExists('admin_notification_subjects'); $assigned = []; if ($tableReady && !empty($admins)) { $adminIds = array_map('intval', array_column($admins, 'id')); $rows = $this->adminNotificationSubjectModel ->select('admin_id') ->where('subject', 'print_requests') ->whereIn('admin_id', $adminIds) ->findAll(); foreach ($rows as $row) { $adminId = (int) ($row['admin_id'] ?? 0); if ($adminId <= 0) { continue; } $assigned[$adminId] = true; } } return [ 'admins' => $admins, 'assigned' => $assigned, 'tableReady' => $tableReady, ]; } public function savePrintRecipients(array $posted): array { if (!$this->db->tableExists('admin_notification_subjects')) { return ['type' => 'error', 'message' => 'Notification subject storage is missing. Run migrations first.']; } $admins = $this->eligibleUsers(); $adminIds = array_map('intval', array_column($admins, 'id')); if (empty($adminIds)) { return ['type' => 'info', 'message' => 'No admins found to update.']; } $selected = []; foreach ($posted as $key => $value) { $adminId = (int) $key; if ($adminId <= 0) { continue; } if (!in_array($adminId, $adminIds, true)) { continue; } $selected[] = $adminId; } $selected = array_values(array_unique($selected)); $existingRows = $this->adminNotificationSubjectModel ->select('admin_id') ->where('subject', 'print_requests') ->whereIn('admin_id', $adminIds) ->findAll(); $current = array_values(array_unique(array_map( fn($row) => (int) ($row['admin_id'] ?? 0), $existingRows ))); $toDelete = array_values(array_diff($current, $selected)); $toInsert = array_values(array_diff($selected, $current)); if (!empty($toDelete)) { $this->adminNotificationSubjectModel ->where('subject', 'print_requests') ->whereIn('admin_id', $toDelete) ->delete(); } if (!empty($toInsert)) { $batch = []; foreach ($toInsert as $adminId) { $batch[] = [ 'admin_id' => $adminId, 'subject' => 'print_requests', ]; } $this->adminNotificationSubjectModel->insertBatch($batch); } $changes = count($toDelete) + count($toInsert); return ['type' => 'success', 'message' => $changes > 0 ? 'Print notification recipients updated.' : 'No changes were made.']; } public function subjectOptions(): array { return [ 'academics' => 'Academics', 'attendance' => 'Attendance', 'events' => 'Events', 'finance' => 'Finance', 'general' => 'General', 'print_requests' => 'Print Requests', ]; } public function excludedRoles(): array { return [ 'parent', 'student', 'guest', 'teacher', 'assistant teacher', 'teacher assistant', 'teacher_assistant', 'assistant_teacher', 'ta', 'authorized_user', ]; } public function eligibleUsers(): array { $excluded = $this->excludedRoles(); $excludedList = "'" . implode("','", $excluded) . "'"; return $this->db->table('users u') ->select('u.id, u.firstname, u.lastname, u.email') ->join('user_roles ur', 'ur.user_id = u.id', 'inner') ->join('roles r', 'r.id = ur.role_id', 'inner') ->where('r.name IS NOT NULL', null, false) ->where('ur.deleted_at', null) ->where("LOWER(r.name) NOT IN ({$excludedList})", null, false) ->groupBy('u.id, u.firstname, u.lastname, u.email') ->orderBy('u.lastname', 'ASC') ->orderBy('u.firstname', 'ASC') ->get() ->getResultArray(); } }