orderBy('incident_datetime', 'DESC'); if ($schoolYear !== null && $schoolYear !== '') { $builder->where('school_year', $schoolYear); } if ($semester !== null && $semester !== '') { $builder->where('semester', $semester); } $incidents = $builder->get()->map(fn ($row) => $row->toArray())->all(); if (empty($incidents)) { return []; } $gradeMap = $this->lookup->gradeNameMap(array_column($incidents, 'grade')); $students = []; foreach ($incidents as $incident) { $studentId = (string) ($incident['student_id'] ?? ''); $studentName = (string) ($incident['student_name'] ?? ''); $studentKey = $studentId !== '' ? 'id:' . $studentId : 'name:' . strtolower(trim($studentName)); $gradeValue = $incident['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) ($incident['incident_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'] = $this->formatIncidentDate($incident['incident_datetime'] ?? null); } $students[$studentKey]['logs'][] = [ 'incident' => $incident['incident'] ?? '', 'incident_state' => $state, 'incident_datetime' => $this->formatIncidentDate($incident['incident_datetime'] ?? null), 'open_description' => $incident['open_description'] ?? null, 'close_description' => $incident['close_description'] ?? null, 'cancel_description' => $incident['cancel_description'] ?? null, 'action_taken' => $incident['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 $studentRows; } private function formatIncidentDate(mixed $value): ?string { if ($value === null || $value === '') { return null; } if ($value instanceof \DateTimeInterface) { return $value->format('Y-m-d H:i:s'); } $raw = (string) $value; $ts = strtotime($raw); if ($ts !== false) { return date('Y-m-d H:i:s', $ts); } return $raw; } }