235 lines
8.2 KiB
PHP
235 lines
8.2 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers\Admin;
|
|
|
|
use App\Http\Controllers\Controller;
|
|
use App\Models\Audition;
|
|
use App\Models\AuditLogEntry;
|
|
use App\Models\Entry;
|
|
use App\Models\Event;
|
|
use App\Models\School;
|
|
use App\Models\Student;
|
|
use Illuminate\Support\Facades\Auth;
|
|
|
|
use function abort;
|
|
use function auth;
|
|
use function compact;
|
|
use function request;
|
|
use function to_route;
|
|
use function view;
|
|
|
|
class StudentController extends Controller
|
|
{
|
|
public function index()
|
|
{
|
|
if (! Auth::user()->is_admin) {
|
|
abort(403);
|
|
}
|
|
$filters = session('adminStudentFilters') ?? null;
|
|
$schools = School::orderBy('name')->get();
|
|
$students = Student::with(['school'])->withCount('entries')->orderBy('last_name')->orderBy('first_name');
|
|
// Apply filters
|
|
if ($filters) {
|
|
if ($filters['first_name']) {
|
|
$students = $students->where('first_name', 'like', '%'.$filters['first_name'].'%');
|
|
}
|
|
if ($filters['last_name']) {
|
|
$students = $students->where('last_name', 'like', '%'.$filters['last_name'].'%');
|
|
}
|
|
if ($filters['school'] && $filters['school'] != 'all') {
|
|
$students = $students->where('school_id', $filters['school']);
|
|
}
|
|
if ($filters['grade'] && $filters['grade'] != 'all') {
|
|
$students = $students->where('grade', $filters['grade']);
|
|
}
|
|
}
|
|
$students = $students->paginate(15);
|
|
$grades = Student::distinct()->pluck('grade');
|
|
|
|
return view('admin.students.index', compact('students', 'schools', 'grades'));
|
|
}
|
|
|
|
public function create()
|
|
{
|
|
if (! Auth::user()->is_admin) {
|
|
abort(403);
|
|
}
|
|
$minGrade = Audition::min('minimum_grade');
|
|
$maxGrade = Audition::max('maximum_grade');
|
|
$schools = School::orderBy('name')->get();
|
|
|
|
return view('admin.students.create', ['schools' => $schools, 'minGrade' => $minGrade, 'maxGrade' => $maxGrade]);
|
|
}
|
|
|
|
public function store()
|
|
{
|
|
if (! Auth::user()->is_admin) {
|
|
abort(403);
|
|
}
|
|
request()->validate([
|
|
'first_name' => ['required'],
|
|
'last_name' => ['required'],
|
|
'grade' => ['required', 'integer'],
|
|
'school_id' => ['required', 'exists:schools,id'],
|
|
]);
|
|
|
|
if (Student::where('first_name', request('first_name'))
|
|
->where('last_name', request('last_name'))
|
|
->where('school_id', request('school_id'))
|
|
->exists()) {
|
|
return redirect('/admin/students/create')->with('error', 'This student already exists.');
|
|
}
|
|
|
|
$student = Student::create([
|
|
'first_name' => request('first_name'),
|
|
'last_name' => request('last_name'),
|
|
'grade' => request('grade'),
|
|
'school_id' => request('school_id'),
|
|
]);
|
|
$message = 'Created student #'.$student->id.' - '.$student->full_name().'<br>Grade: '.$student->grade.'<br>School: '.$student->school->name;
|
|
AuditLogEntry::create([
|
|
'user' => auth()->user()->email,
|
|
'ip_address' => request()->ip(),
|
|
'message' => $message,
|
|
'affected' => [
|
|
'students' => [$student->id],
|
|
'schools' => [$student->school_id],
|
|
],
|
|
]);
|
|
|
|
return redirect('/admin/students')->with('success', 'Created student successfully');
|
|
}
|
|
|
|
public function edit(Student $student)
|
|
{
|
|
if (! Auth::user()->is_admin) {
|
|
abort(403);
|
|
}
|
|
$minGrade = Audition::min('minimum_grade');
|
|
$maxGrade = Audition::max('maximum_grade');
|
|
$schools = School::orderBy('name')->get();
|
|
$student->loadCount('entries');
|
|
$entries = $student->entries;
|
|
$events = Event::all();
|
|
$event_entries = [];
|
|
foreach ($events as $event) {
|
|
$event_entries[$event->id] = $entries->filter(function ($entry) use ($event) {
|
|
return $event->id === $entry->audition->event_id;
|
|
});
|
|
// Check if doubler status can change
|
|
foreach ($event_entries[$event->id] as $entry) {
|
|
$entry->doubler_decision_frozen = $this->isDoublerStatusFrozen($entry, $event_entries[$event->id]);
|
|
}
|
|
}
|
|
|
|
return view('admin.students.edit',
|
|
compact('student', 'schools', 'minGrade', 'maxGrade', 'events', 'event_entries'));
|
|
}
|
|
|
|
private function isDoublerStatusFrozen(Entry $entry, $entries)
|
|
{
|
|
// Can't change decision if results are published
|
|
if ($entry->audition->hasFlag('seats_published')) {
|
|
return true;
|
|
}
|
|
|
|
// Can't change decision if this is the only entry
|
|
if ($entries->count() === 1) {
|
|
return true;
|
|
}
|
|
|
|
// Can't change decision if this is the only entry with results not published
|
|
$unpublished = $entries->reject(function ($entry) {
|
|
return $entry->audition->hasFlag('seats_published');
|
|
});
|
|
if ($unpublished->count() < 2) {
|
|
return true;
|
|
}
|
|
|
|
// Can't change decision if we've accepted another audition
|
|
foreach ($entries as $checkEntry) {
|
|
if ($checkEntry->audition->hasFlag('seats_published') && ! $checkEntry->hasFlag('declined')) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public function update(Student $student)
|
|
{
|
|
if (! Auth::user()->is_admin) {
|
|
abort(403);
|
|
}
|
|
request()->validate([
|
|
'first_name' => ['required'],
|
|
'last_name' => ['required'],
|
|
'grade' => ['required', 'integer'],
|
|
'school_id' => ['required', 'exists:schools,id'],
|
|
]);
|
|
|
|
foreach ($student->entries as $entry) {
|
|
if ($entry->audition->minimum_grade > request('grade') || $entry->audition->maximum_grade < request('grade')) {
|
|
return redirect('/admin/students/'.$student->id.'/edit')->with('error',
|
|
'This student is entered in an audition that is not available to their new grade.');
|
|
}
|
|
}
|
|
|
|
if (Student::where('first_name', request('first_name'))
|
|
->where('last_name', request('last_name'))
|
|
->where('school_id', request('school_id'))
|
|
->where('id', '!=', $student->id)
|
|
->exists()) {
|
|
return redirect('/admin/students/'.$student->id.'/edit')->with('error',
|
|
'A student with that name already exists at that school');
|
|
}
|
|
|
|
$student->update([
|
|
'first_name' => request('first_name'),
|
|
'last_name' => request('last_name'),
|
|
'grade' => request('grade'),
|
|
'school_id' => request('school_id'),
|
|
]);
|
|
|
|
$message = 'Updated student #'.$student->id.'<br>Name: '.$student->full_name().'<br>Grade: '.$student->grade.'<br>School: '.$student->school->name;
|
|
AuditLogEntry::create([
|
|
'user' => auth()->user()->email,
|
|
'ip_address' => request()->ip(),
|
|
'message' => $message,
|
|
'affected' => [
|
|
'students' => [$student->id],
|
|
'schools' => [$student->school_id],
|
|
],
|
|
]);
|
|
|
|
return redirect('/admin/students')->with('success', 'Student updated');
|
|
|
|
}
|
|
|
|
public function destroy(Student $student)
|
|
{
|
|
if ($student->entries()->count() > 0) {
|
|
return to_route('admin.students.index')->with('error', 'You cannot delete a student with entries.');
|
|
}
|
|
$name = $student->full_name();
|
|
$message = 'Deleted student #'.$student->id.'<br>Name: '.$student->full_name().'<br>Grade: '.$student->grade.'<br>School: '.$student->school->name;
|
|
AuditLogEntry::create([
|
|
'user' => auth()->user()->email,
|
|
'ip_address' => request()->ip(),
|
|
'message' => $message,
|
|
'affected' => [
|
|
'students' => [$student->id],
|
|
'schools' => [$student->school_id],
|
|
],
|
|
]);
|
|
$student->delete();
|
|
|
|
return to_route('admin.students.index')->with('success', 'Student '.$name.' deleted successfully.');
|
|
}
|
|
|
|
public function set_filter()
|
|
{
|
|
//
|
|
}
|
|
}
|