Files
alrahma_sunday_school_api/app/Services/Incidents/IncidentAnalysisService.php
T
2026-06-11 11:46:12 -04:00

111 lines
3.8 KiB
PHP

<?php
namespace App\Services\Incidents;
use App\Models\Incident;
class IncidentAnalysisService
{
public function __construct(private IncidentLookupService $lookup) {}
public function analyze(?string $schoolYear, ?string $semester): array
{
$builder = Incident::query()->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;
}
}