db = \Config\Database::connect(); //$this->userModel = new UserModel(); helper(['url', 'form']); } public function index() { $currentFlagModel = new CurrentFlagModel(); $classSectionModel = new ClassSectionModel(); $studentClassModel = new StudentClassModel(); $configModel = new ConfigurationModel(); // Format grades with id and name for passing to the view $grades = []; // Retrieve flags and class sections that currently have active students $flags = $currentFlagModel->findAll(); $schoolYear = $configModel->getConfig('school_year'); $studentCounts = $studentClassModel->getStudentCountsBySection($schoolYear); $classSections = []; if (!empty($studentCounts)) { $classSectionIdsWithStudents = array_keys($studentCounts); $classSections = $classSectionModel ->orderBy('class_section_name', 'ASC') ->whereIn('class_section_id', $classSectionIdsWithStudents) ->findAll(); } foreach ($classSections as $section) { $grades[] = [ 'id' => $section['class_section_id'], 'name' => $section['class_section_name'] ]; } // Map updater user IDs to display names for the view $updaterIds = []; foreach ($flags as $flag) { foreach (['updated_by_open', 'updated_by_closed', 'updated_by_canceled'] as $key) { if (!empty($flag[$key])) { $updaterIds[(int)$flag[$key]] = true; } } } $updaterMap = []; if (!empty($updaterIds)) { $rows = $this->db->table('users') ->select('id, firstname, lastname') ->whereIn('id', array_keys($updaterIds)) ->get() ->getResultArray(); foreach ($rows as $row) { $name = trim((string)($row['firstname'] ?? '') . ' ' . (string)($row['lastname'] ?? '')); $updaterMap[(int)$row['id']] = $name !== '' ? $name : ('User #' . $row['id']); } } foreach ($flags as &$flag) { foreach (['updated_by_open', 'updated_by_closed', 'updated_by_canceled'] as $key) { $id = (int)($flag[$key] ?? 0); $flag[$key . '_name'] = $id > 0 ? ($updaterMap[$id] ?? null) : null; } } unset($flag); // Pass flags and formatted grades to the view return view('flags/flags_management', [ 'flags' => $flags, 'grades' => $grades // Now grades include both id and class_section_name ]); } public function history() { $flagModel = new FlagModel(); $schoolYear = (string)($this->request->getGet('school_year') ?? ''); $semester = (string)($this->request->getGet('semester') ?? ''); $builder = $flagModel->orderBy('flag_datetime', 'DESC'); if ($schoolYear !== '') { $builder->where('school_year', $schoolYear); } if ($semester !== '') { $builder->where('semester', $semester); } return $this->response->setJSON([ 'flags' => $builder->findAll(), ]); } public function processedFlags() { $flagModel = new FlagModel(); $classSectionModel = new ClassSectionModel(); $schoolYear = (string)($this->request->getGet('school_year') ?? ''); $semester = (string)($this->request->getGet('semester') ?? ''); $builder = $flagModel->orderBy('flag_datetime', 'DESC'); if ($schoolYear !== '') { $builder->where('school_year', $schoolYear); } if ($semester !== '') { $builder->where('semester', $semester); } $flags = $builder->findAll(); $gradeIds = []; foreach ($flags as $flag) { $gradeValue = $flag['grade'] ?? ''; if (is_numeric($gradeValue)) { $gradeIds[(int)$gradeValue] = true; } } $gradeMap = []; if (!empty($gradeIds)) { $rows = $classSectionModel ->select('class_section_id, class_section_name') ->whereIn('class_section_id', array_keys($gradeIds)) ->findAll(); foreach ($rows as $row) { $gradeMap[(int)$row['class_section_id']] = (string)($row['class_section_name'] ?? ''); } } // Map updater user IDs to display names for the view $updaterIds = []; foreach ($flags as $flag) { foreach (['updated_by_open', 'updated_by_closed', 'updated_by_canceled'] as $key) { if (!empty($flag[$key])) { $updaterIds[(int)$flag[$key]] = true; } } } $updaterMap = []; if (!empty($updaterIds)) { $rows = $this->db->table('users') ->select('id, firstname, lastname') ->whereIn('id', array_keys($updaterIds)) ->get() ->getResultArray(); foreach ($rows as $row) { $name = trim((string)($row['firstname'] ?? '') . ' ' . (string)($row['lastname'] ?? '')); $updaterMap[(int)$row['id']] = $name !== '' ? $name : ('User #' . $row['id']); } } foreach ($flags as &$flag) { foreach (['updated_by_open', 'updated_by_closed', 'updated_by_canceled'] as $key) { $id = (int)($flag[$key] ?? 0); $flag[$key . '_name'] = $id > 0 ? ($updaterMap[$id] ?? null) : null; } $gradeValue = $flag['grade'] ?? ''; if (is_numeric($gradeValue)) { $flag['grade'] = $gradeMap[(int)$gradeValue] ?? (string)$gradeValue; } } unset($flag); return view('flags/processed_flags', [ 'flags' => $flags ]); } public function incidentAnalysis() { $flagModel = new FlagModel(); $classSectionModel = new ClassSectionModel(); $schoolYear = (string)($this->request->getGet('school_year') ?? ''); $semester = (string)($this->request->getGet('semester') ?? ''); $builder = $flagModel->orderBy('flag_datetime', 'DESC'); if ($schoolYear !== '') { $builder->where('school_year', $schoolYear); } if ($semester !== '') { $builder->where('semester', $semester); } $flags = $builder->findAll(); $gradeIds = []; foreach ($flags as $flag) { $gradeValue = $flag['grade'] ?? ''; if (is_numeric($gradeValue)) { $gradeIds[(int)$gradeValue] = true; } } $gradeMap = []; if (!empty($gradeIds)) { $rows = $classSectionModel ->select('class_section_id, class_section_name') ->whereIn('class_section_id', array_keys($gradeIds)) ->findAll(); foreach ($rows as $row) { $gradeMap[(int)$row['class_section_id']] = (string)($row['class_section_name'] ?? ''); } } $students = []; foreach ($flags as $flag) { $studentId = (string)($flag['student_id'] ?? ''); $studentName = (string)($flag['student_name'] ?? ''); $studentKey = $studentId !== '' ? 'id:' . $studentId : 'name:' . strtolower(trim($studentName)); $gradeValue = $flag['grade'] ?? ''; $gradeLabel = $gradeValue; if (is_numeric($gradeValue)) { $gradeLabel = $gradeMap[(int)$gradeValue] ?? (string)$gradeValue; } if (!isset($students[$studentKey])) { $students[$studentKey] = [ 'student_id' => $studentId, 'student_name' => $studentName, 'grade' => (string)$gradeLabel, 'total' => 0, 'open' => 0, 'closed' => 0, 'canceled' => 0, 'last_incident' => null, 'logs' => [], ]; } $students[$studentKey]['total'] += 1; $state = (string)($flag['flag_state'] ?? ''); if ($state === 'Open') { $students[$studentKey]['open'] += 1; } elseif ($state === 'Closed') { $students[$studentKey]['closed'] += 1; } elseif ($state === 'Canceled') { $students[$studentKey]['canceled'] += 1; } if ($students[$studentKey]['last_incident'] === null) { $students[$studentKey]['last_incident'] = $flag['flag_datetime'] ?? null; } $students[$studentKey]['logs'][] = [ 'flag' => $flag['flag'] ?? '', 'flag_state' => $state, 'flag_datetime' => $flag['flag_datetime'] ?? null, 'open_description' => $flag['open_description'] ?? null, 'close_description' => $flag['close_description'] ?? null, 'cancel_description' => $flag['cancel_description'] ?? null, 'action_taken' => $flag['action_taken'] ?? null, ]; } $studentRows = array_values($students); usort($studentRows, function ($a, $b) { if ($a['total'] === $b['total']) { return strcasecmp($a['student_name'], $b['student_name']); } return $b['total'] <=> $a['total']; }); return view('flags/incident_analysis', [ 'students' => $studentRows, 'schoolYear' => $schoolYear, 'semester' => $semester, ]); } public function getStudentsByGrade($gradeId) { $studentClassModel = new StudentClassModel(); // Model for the student_class table $studentModel = new StudentModel(); // Model for the students table // Fetch student IDs for the selected grade $studentIds = $studentClassModel ->active() ->where('student_class.class_section_id', $gradeId) ->findColumn('student_id'); // If no student IDs are found, return an empty JSON array if (empty($studentIds)) { return $this->response->setJSON([]); } // Fetch student details from students table using the retrieved IDs $students = $studentModel ->whereIn('id', $studentIds) ->where('is_active', 1) ->findAll(); // Prepare data for JSON response with both ID and full name $studentData = []; foreach ($students as $student) { $studentData[] = [ 'id' => $student['id'], // Student ID 'name' => $student['firstname'] . ' ' . $student['lastname'] // Full name ]; } // Return JSON response with student ID and full name return $this->response->setJSON($studentData); } public function addFlag() { $currentFlagModel = new CurrentFlagModel(); $studentModel = new StudentModel(); $configModel = new ConfigurationModel(); // Get the data from the form submission $studentId = $this->request->getPost('student'); $flagType = $this->request->getPost('flag'); $description = $this->request->getPost('description'); $flagState = $this->request->getPost('flag_state'); $stateDescription = $this->request->getPost('state_description'); // Additional description for "Closed" or "Canceled" // Retrieve student information from the database $student = $studentModel->find($studentId); if (!$student) { session()->setFlashdata('error', 'Student not found.'); return $this->index(); } // Get the user_id from the session for updated_by $userId = session()->get('user_id'); // Get the semester and school year from configuration $semester = $configModel->getConfig('semester'); $schoolYear = $configModel->getConfig('school_year'); // Set the current system date and time for flag_datetime $currentDateTime = utc_now(); // Check if a flag of the same type already exists for this student $existingFlag = $currentFlagModel->where('student_id', $studentId) ->where('flag', $flagType) ->first(); if ($existingFlag) { // If the flag exists, update it based on the new state and description $data = [ 'flag_datetime' => $currentDateTime, 'updated_by_open' => $userId ]; // Append the new description to the appropriate field based on flag state if ($flagState === 'Closed') { $data['flag_state'] = 'Closed'; $data['close_description'] = ($existingFlag['close_description'] ?? '') . PHP_EOL . $stateDescription; } elseif ($flagState === 'Canceled') { $data['flag_state'] = 'Canceled'; $data['cancel_description'] = ($existingFlag['cancel_description'] ?? '') . PHP_EOL . $stateDescription; } else { $data['open_description'] = $existingFlag['open_description'] . PHP_EOL . $description; } // Update the existing flag $currentFlagModel->update($existingFlag['id'], $data); session()->setFlashdata('success', 'Flag updated successfully!'); } else { // If no existing flag is found, prepare the data for insertion $data = [ 'student_id' => $student['id'], 'student_name' => $student['firstname'] . ' ' . $student['lastname'], 'grade' => $this->request->getPost('grade'), 'flag' => $flagType, 'flag_datetime' => $currentDateTime, 'flag_state' => 'Open', // Set initial state to 'Open' 'updated_by_open' => $userId, 'open_description' => $description, 'semester' => $semester, 'school_year' => $schoolYear ]; // Insert the new flag if ($currentFlagModel->insert($data)) { session()->setFlashdata('success', 'New incident added successfully!'); } else { session()->setFlashdata('error', 'Failed to add new incident.'); } } // Redirect to the list view return $this->index(); } public function updateState($id) { log_message('debug', 'updateState method called for ID: ' . $id); log_message('debug', 'Flag state: ' . $this->request->getPost('flag_state')); $currentFlagModel = new CurrentFlagModel(); // Get the new flag state from the form $newState = $this->request->getPost('flag_state'); if (!$newState) { session()->setFlashdata('error', 'incident state not provided.'); return $this->index(); } // Update the flag state in the database if ($currentFlagModel->update($id, ['flag_state' => $newState])) { session()->setFlashdata('success', 'Incident state updated successfully!'); } else { $errors = $currentFlagModel->errors(); log_message('error', 'Failed to update incident state: ' . print_r($errors, true)); session()->setFlashdata('error', 'Failed to update incident state.'); } // Redirect back to the flags list return $this->index(); } public function closeFlag($flagId) { // Log the whole session array log_message('debug', json_encode(session()->get())); $currentFlagModel = new CurrentFlagModel(); $userId = session()->get('user_id'); // Get the current flag data $flagData = $currentFlagModel->find($flagId); // Log and check if flag data is found if (!$flagData) { log_message('error', "incident with ID {$flagId} not found in database."); session()->setFlashdata('error', 'Incident not found.'); return redirect()->back(); } // Proceed only if flag is not closed if ($flagData['flag_state'] !== 'Closed') { // Retrieve 'close_description' from POST request $closeDescription = $this->request->getPost('state_description'); $actionTaken = $this->request->getPost('action_taken'); // Debugging: Check if the close description is received if (empty($closeDescription)) { session()->setFlashdata('error', 'Close description is missing.'); return redirect()->back(); } // Update the flag state to Closed $currentFlagModel->update($flagId, [ 'flag_state' => 'Closed', 'updated_by_closed' => $userId, 'close_description' => $closeDescription, // Use dynamic description from form 'action_taken' => $actionTaken ]); $flagData = $currentFlagModel->find($flagId); return $this->moveToHistory($flagData); } else { session()->setFlashdata('error', 'Incident is already closed.'); } return $this->index(); } public function cancelFlag($flagId) { $currentFlagModel = new CurrentFlagModel(); $userId = session()->get('user_id'); // Retrieve 'cancel_description' from POST request $cancelDescription = $this->request->getPost('state_description'); $actionTaken = $this->request->getPost('action_taken'); // Get the current flag data $flagData = $currentFlagModel->find($flagId); // Check if flag data is found if (!$flagData) { log_message('error', "Incident with ID {$flagId} not found in database."); session()->setFlashdata('error', 'Incident not found.'); return redirect()->back(); } // Check if the flag is not already canceled if ($flagData['flag_state'] !== 'Canceled') { // Update the flag state to Canceled $currentFlagModel->update($flagId, [ 'flag_state' => 'Canceled', 'updated_by_canceled' => $userId, 'cancel_description' => $cancelDescription, 'action_taken' => $actionTaken ]); // Retrieve updated flag data to ensure latest state $flagData = $currentFlagModel->find($flagId); return $this->moveToHistory($flagData); } else { session()->setFlashdata('error', 'Incident is already canceled.'); } return $this->index(); } private function moveToHistory($flagData) { $flagModel = new FlagModel(); // Prepare data for the flag table $dataToInsert = [ 'student_id' => $flagData['student_id'], 'student_name' => $flagData['student_name'], 'grade' => $flagData['grade'], 'flag' => $flagData['flag'], 'flag_datetime' => $flagData['flag_datetime'], 'flag_state' => $flagData['flag_state'], 'updated_by_open' => $flagData['updated_by_open'], 'open_description' => $flagData['open_description'], 'updated_by_closed' => $flagData['updated_by_closed'], 'close_description' => $flagData['close_description'], 'action_taken' => $flagData['action_taken'], 'updated_by_canceled' => $flagData['updated_by_canceled'], 'cancel_description' => $flagData['cancel_description'], 'semester' => $flagData['semester'], 'school_year' => $flagData['school_year'], 'created_at' => $flagData['created_at'], 'updated_at' => $flagData['updated_at'] ]; // Insert data into the flag table if ($flagModel->insert($dataToInsert)) { // Delete the entry from the current_flag table $currentFlagModel = new CurrentFlagModel(); $currentFlagModel->delete($flagData['id']); session()->setFlashdata('success', 'Incident has been moved to history.'); } else { session()->setFlashdata('error', 'Failed to move incident to history.'); } return $this->index(); } }