From d292331a1e494bf40edc36a008c17d60370bdfa0 Mon Sep 17 00:00:00 2001 From: Matt Young Date: Wed, 17 Jul 2024 14:04:30 -0500 Subject: [PATCH] Admin createEntry action in user entry creation #29 Creating an entry should check on the status of the draw and respond appropriately Also addresses #37 --- .../Controllers/Admin/EntryController.php | 25 +++++++---- app/Http/Controllers/EntryController.php | 4 ++ .../Feature/Pages/Admin/EntiesCreateTest.php | 42 ++++++++++++++++++- tests/Feature/Pages/EntriesIndexTest.php | 19 +++++++++ 4 files changed, 81 insertions(+), 9 deletions(-) diff --git a/app/Http/Controllers/Admin/EntryController.php b/app/Http/Controllers/Admin/EntryController.php index a04da74..ab55ea0 100644 --- a/app/Http/Controllers/Admin/EntryController.php +++ b/app/Http/Controllers/Admin/EntryController.php @@ -2,7 +2,9 @@ namespace App\Http\Controllers\Admin; +use App\Actions\CreateEntry; use App\Actions\Tabulation\CalculateEntryScore; +use App\Exceptions\CreateEntryException; use App\Http\Controllers\Controller; use App\Models\Audition; use App\Models\Entry; @@ -87,7 +89,7 @@ class EntryController extends Controller return view('admin.entries.create', ['students' => $students, 'auditions' => $auditions]); } - public function store(Request $request) + public function store(Request $request, CreateEntry $creator) { if (! Auth::user()->is_admin) { abort(403); @@ -99,15 +101,21 @@ class EntryController extends Controller $validData['for_seating'] = $request->get('for_seating') ? 1 : 0; $validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0; + $enter_for = []; + if ($validData['for_seating']) { + $enter_for[] = 'seating'; + } + if ($validData['for_advancement']) { + $enter_for[] = 'advancement'; + } - Entry::create([ - 'student_id' => $validData['student_id'], - 'audition_id' => $validData['audition_id'], - 'for_seating' => $validData['for_seating'], - 'for_advancement' => $validData['for_advancement'], - ]); + try { + $creator($validData['student_id'], $validData['audition_id'], $enter_for); + } catch (CreateEntryException $ex) { + return redirect()->route('admin.entries.index')->with('error', $ex->getMessage()); + } - return redirect('/admin/entries'); + return redirect(route('admin.entries.index'))->with('success', 'The entry has been added.'); } public function edit(Entry $entry, CalculateEntryScore $calculator) @@ -126,6 +134,7 @@ class EntryController extends Controller $auditions = Audition::orderBy('score_order')->get(); $scores = $entry->scoreSheets()->with('audition', 'judge')->get(); $scores->each(fn ($score) => $score->entry = $entry); + // return view('admin.entries.edit', ['entry' => $entry, 'students' => $students, 'auditions' => $auditions]); return view('admin.entries.edit', compact('entry', 'students', 'auditions', 'scores')); } diff --git a/app/Http/Controllers/EntryController.php b/app/Http/Controllers/EntryController.php index 3180d46..f2e7ca4 100644 --- a/app/Http/Controllers/EntryController.php +++ b/app/Http/Controllers/EntryController.php @@ -36,6 +36,10 @@ class EntryController extends Controller 'student_id' => ['required', 'exists:students,id'], 'audition_id' => ['required', 'exists:auditions,id'], ]); + $audition = Audition::find($validData['audition_id']); + if ($audition->entry_deadline < now()) { + return redirect()->route('entries.index')->with('error', 'The entry deadline for that audition has passed'); + } $validData['for_seating'] = $request->get('for_seating') ? 1 : 0; $validData['for_advancement'] = $request->get('for_advancement') ? 1 : 0; diff --git a/tests/Feature/Pages/Admin/EntiesCreateTest.php b/tests/Feature/Pages/Admin/EntiesCreateTest.php index dc71571..3142c0f 100644 --- a/tests/Feature/Pages/Admin/EntiesCreateTest.php +++ b/tests/Feature/Pages/Admin/EntiesCreateTest.php @@ -4,6 +4,7 @@ use App\Models\Audition; use App\Models\Student; use Illuminate\Foundation\Testing\RefreshDatabase; +use function Pest\Laravel\assertDatabaseHas; use function Pest\Laravel\get; use function PHPUnit\Framework\assertEquals; @@ -19,7 +20,7 @@ it('does not respond to a guest', function () { get(route('admin.entries.create')) ->assertRedirect(route('home')); }); -it('passes a collection of all students with thier schools to the view', function () { +it('passes a collection of all students with their schools to the view', function () { // Arrange Student::factory()->count(8)->create(); $students = Student::with('school')->orderBy('last_name')->orderBy('first_name')->get(); @@ -47,3 +48,42 @@ it('passes a collection of available auditions to the view', function () { $response->assertOk(); assertEquals(array_values($auditions), array_values($viewAuditions)); }); +it('can create an entry', function () { + $audition = Audition::factory()->create(['maximum_grade' => 12, 'minimum_grade' => 7]); + $student = Student::factory()->create(['grade' => 9]); + actAsAdmin(); + $response = $this->post(route('admin.entries.store'), [ + 'student_id' => $student->id, + 'audition_id' => $audition->id, + 'for_seating' => 'on', + ]); + $response->assertRedirect(route('admin.entries.index')) + ->assertSessionDoesntHaveErrors() + ->assertSessionHas('success', 'The entry has been added.'); + assertDatabaseHas('entries', [ + 'student_id' => $student->id, + 'audition_id' => $audition->id, + 'for_seating' => 1, + 'for_advancement' => 0, + ]); +}); +it('can create a late entry', function () { + $audition = Audition::factory()->closed()->create(['maximum_grade' => 12, 'minimum_grade' => 7]); + $student = Student::factory()->create(['grade' => 9]); + actAsAdmin(); + $response = $this->post(route('admin.entries.store'), [ + 'student_id' => $student->id, + 'audition_id' => $audition->id, + 'for_seating' => 'on', + ]); + $response->assertRedirect(route('admin.entries.index')) + ->assertSessionDoesntHaveErrors() + ->assertSessionMissing('error') + ->assertSessionHas('success', 'The entry has been added.'); + assertDatabaseHas('entries', [ + 'student_id' => $student->id, + 'audition_id' => $audition->id, + 'for_seating' => 1, + 'for_advancement' => 0, + ]); +}); diff --git a/tests/Feature/Pages/EntriesIndexTest.php b/tests/Feature/Pages/EntriesIndexTest.php index 6ecc175..2df03aa 100644 --- a/tests/Feature/Pages/EntriesIndexTest.php +++ b/tests/Feature/Pages/EntriesIndexTest.php @@ -9,6 +9,7 @@ use App\Settings; use Illuminate\Foundation\Testing\RefreshDatabase; use function Pest\Laravel\actingAs; +use function Pest\Laravel\assertDatabaseMissing; use function Pest\Laravel\delete; use function Pest\Laravel\get; use function Pest\Laravel\post; @@ -180,3 +181,21 @@ it('shows entry type checkboxes only when advancement is enabled', function () { get(route('entries.index')) ->assertDontSee('Enter for'); }); +it('denies an entry that is late', function () { + // Arrnge + $student = Student::factory()->create(['school_id' => $this->school->id, 'grade' => 8]); + $audition = Audition::factory()->closed()->create(['maximum_grade' => 9, 'minimum_grade' => 7]); + $user = User::factory()->create(['school_id' => $student->school_id]); + actingAs($user); + // Act & Assert + $response = post(route('entries.store'), [ + 'student_id' => $student->id, + 'audition_id' => $audition->id, + ]); + assertDatabaseMissing('entries', [ + 'student_id' => $student->id, + 'audition_id' => $audition->id, + ]); + $response->assertRedirect(route('entries.index')) + ->assertSessionHas('error', 'The entry deadline for that audition has passed'); +});