234 lines
8.0 KiB
PHP
234 lines
8.0 KiB
PHP
<?php
|
|
|
|
namespace App\Services\Incidents;
|
|
|
|
use App\Models\Configuration;
|
|
use App\Models\CurrentIncident;
|
|
use App\Models\Incident;
|
|
use App\Models\Student;
|
|
use App\Models\StudentClass;
|
|
use Illuminate\Support\Facades\DB;
|
|
|
|
class CurrentIncidentService
|
|
{
|
|
public function __construct(private IncidentLookupService $lookup)
|
|
{
|
|
}
|
|
|
|
public function listCurrent(): array
|
|
{
|
|
$incidents = CurrentIncident::query()->get()->map(fn ($row) => $row->toArray())->all();
|
|
$schoolYear = Configuration::getConfig('school_year');
|
|
|
|
$updaterIds = [];
|
|
foreach ($incidents as $incident) {
|
|
foreach (['updated_by_open', 'updated_by_closed', 'updated_by_canceled'] as $key) {
|
|
if (!empty($incident[$key])) {
|
|
$updaterIds[] = (int) $incident[$key];
|
|
}
|
|
}
|
|
}
|
|
|
|
$updaterMap = $this->lookup->updaterNameMap($updaterIds);
|
|
foreach ($incidents as &$incident) {
|
|
foreach (['updated_by_open', 'updated_by_closed', 'updated_by_canceled'] as $key) {
|
|
$id = (int) ($incident[$key] ?? 0);
|
|
$incident[$key . '_name'] = $id > 0 ? ($updaterMap[$id] ?? null) : null;
|
|
}
|
|
}
|
|
unset($incident);
|
|
|
|
return [
|
|
'incidents' => $incidents,
|
|
'grades' => $this->lookup->gradeOptionsWithActiveStudents($schoolYear),
|
|
];
|
|
}
|
|
|
|
public function studentsByGrade(int $gradeId): array
|
|
{
|
|
$studentIds = StudentClass::query()
|
|
->active()
|
|
->where('student_class.class_section_id', $gradeId)
|
|
->pluck('student_id')
|
|
->all();
|
|
|
|
if (empty($studentIds)) {
|
|
return [];
|
|
}
|
|
|
|
return Student::query()
|
|
->whereIn('id', $studentIds)
|
|
->where('is_active', 1)
|
|
->get()
|
|
->map(fn ($student) => [
|
|
'id' => (int) $student->id,
|
|
'name' => trim((string) $student->firstname . ' ' . (string) $student->lastname),
|
|
])
|
|
->all();
|
|
}
|
|
|
|
public function addIncident(array $payload, int $userId): array
|
|
{
|
|
$studentId = (int) $payload['student_id'];
|
|
$incidentType = (string) $payload['incident'];
|
|
$description = (string) ($payload['description'] ?? '');
|
|
$incidentState = (string) ($payload['incident_state'] ?? 'Open');
|
|
$stateDescription = (string) ($payload['state_description'] ?? '');
|
|
$grade = (string) $payload['grade'];
|
|
|
|
$student = Student::query()->find($studentId);
|
|
if (!$student) {
|
|
return [
|
|
'ok' => false,
|
|
'message' => 'Student not found.',
|
|
];
|
|
}
|
|
|
|
$semester = Configuration::getConfig('semester');
|
|
$schoolYear = Configuration::getConfig('school_year');
|
|
$currentDateTime = function_exists('utc_now') ? utc_now() : now('UTC')->toDateTimeString();
|
|
|
|
$existingIncident = CurrentIncident::query()
|
|
->where('student_id', $studentId)
|
|
->where('incident', $incidentType)
|
|
->first();
|
|
|
|
if ($existingIncident) {
|
|
$data = [
|
|
'incident_datetime' => $currentDateTime,
|
|
'updated_by_open' => $userId,
|
|
];
|
|
|
|
if ($incidentState === 'Closed') {
|
|
$data['incident_state'] = 'Closed';
|
|
$data['close_description'] = $this->appendLine($existingIncident->close_description ?? '', $stateDescription);
|
|
} elseif ($incidentState === 'Canceled') {
|
|
$data['incident_state'] = 'Canceled';
|
|
$data['cancel_description'] = $this->appendLine($existingIncident->cancel_description ?? '', $stateDescription);
|
|
} else {
|
|
$data['open_description'] = $this->appendLine($existingIncident->open_description ?? '', $description);
|
|
}
|
|
|
|
$existingIncident->fill($data);
|
|
$existingIncident->save();
|
|
|
|
return [
|
|
'ok' => true,
|
|
'created' => false,
|
|
'incident_id' => (int) $existingIncident->id,
|
|
];
|
|
}
|
|
|
|
$incident = CurrentIncident::query()->create([
|
|
'student_id' => $student->id,
|
|
'student_name' => trim((string) $student->firstname . ' ' . (string) $student->lastname),
|
|
'grade' => $grade,
|
|
'incident' => $incidentType,
|
|
'incident_datetime' => $currentDateTime,
|
|
'incident_state' => 'Open',
|
|
'updated_by_open' => $userId,
|
|
'open_description' => $description,
|
|
'semester' => $semester,
|
|
'school_year' => $schoolYear,
|
|
]);
|
|
|
|
return [
|
|
'ok' => true,
|
|
'created' => true,
|
|
'incident_id' => (int) $incident->id,
|
|
];
|
|
}
|
|
|
|
public function updateState(int $incidentId, string $newState): bool
|
|
{
|
|
return CurrentIncident::query()->whereKey($incidentId)->update([
|
|
'incident_state' => $newState,
|
|
]) > 0;
|
|
}
|
|
|
|
public function closeIncident(int $incidentId, string $closeDescription, ?string $actionTaken, int $userId): array
|
|
{
|
|
$incident = CurrentIncident::query()->find($incidentId);
|
|
if (!$incident) {
|
|
return ['ok' => false, 'message' => 'Incident not found.'];
|
|
}
|
|
|
|
if ($incident->incident_state === 'Closed') {
|
|
return ['ok' => false, 'message' => 'Incident is already closed.'];
|
|
}
|
|
|
|
$incident->fill([
|
|
'incident_state' => 'Closed',
|
|
'updated_by_closed' => $userId,
|
|
'close_description' => $closeDescription,
|
|
'action_taken' => $actionTaken,
|
|
]);
|
|
$incident->save();
|
|
|
|
return $this->moveToHistory($incident);
|
|
}
|
|
|
|
public function cancelIncident(int $incidentId, ?string $cancelDescription, ?string $actionTaken, int $userId): array
|
|
{
|
|
$incident = CurrentIncident::query()->find($incidentId);
|
|
if (!$incident) {
|
|
return ['ok' => false, 'message' => 'Incident not found.'];
|
|
}
|
|
|
|
if ($incident->incident_state === 'Canceled') {
|
|
return ['ok' => false, 'message' => 'Incident is already canceled.'];
|
|
}
|
|
|
|
$incident->fill([
|
|
'incident_state' => 'Canceled',
|
|
'updated_by_canceled' => $userId,
|
|
'cancel_description' => $cancelDescription,
|
|
'action_taken' => $actionTaken,
|
|
]);
|
|
$incident->save();
|
|
|
|
return $this->moveToHistory($incident);
|
|
}
|
|
|
|
private function moveToHistory(CurrentIncident $incident): array
|
|
{
|
|
return DB::transaction(function () use ($incident) {
|
|
$history = Incident::query()->create([
|
|
'student_id' => $incident->student_id,
|
|
'student_name' => $incident->student_name,
|
|
'grade' => $incident->grade,
|
|
'incident' => $incident->incident,
|
|
'incident_datetime' => $incident->incident_datetime,
|
|
'incident_state' => $incident->incident_state,
|
|
'updated_by_open' => $incident->updated_by_open,
|
|
'open_description' => $incident->open_description,
|
|
'updated_by_closed' => $incident->updated_by_closed,
|
|
'close_description' => $incident->close_description,
|
|
'action_taken' => $incident->action_taken,
|
|
'updated_by_canceled' => $incident->updated_by_canceled,
|
|
'cancel_description' => $incident->cancel_description,
|
|
'semester' => $incident->semester,
|
|
'school_year' => $incident->school_year,
|
|
'created_at' => $incident->created_at,
|
|
'updated_at' => $incident->updated_at,
|
|
]);
|
|
|
|
$incident->delete();
|
|
|
|
return [
|
|
'ok' => true,
|
|
'incident_id' => (int) $history->id,
|
|
];
|
|
});
|
|
}
|
|
|
|
private function appendLine(string $existing, string $append): string
|
|
{
|
|
if ($existing === '') {
|
|
return $append;
|
|
}
|
|
|
|
return $existing . PHP_EOL . $append;
|
|
}
|
|
}
|