Auditionadmin 29 #40
|
|
@ -0,0 +1,82 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
|
|
||||||
|
namespace App\Actions;
|
||||||
|
|
||||||
|
use App\Exceptions\CreateEntryException;
|
||||||
|
use App\Models\Audition;
|
||||||
|
use App\Models\Entry;
|
||||||
|
use App\Models\Student;
|
||||||
|
|
||||||
|
class CreateEntry
|
||||||
|
{
|
||||||
|
public function __construct()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
public function __invoke(Student $student, Audition $audition, string|array|null $entry_for = null): void
|
||||||
|
{
|
||||||
|
$this->createEntry($student, $audition, $entry_for);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function createEntry(Student $student, Audition $audition, string|array|null $entry_for = null)
|
||||||
|
{
|
||||||
|
if (! $entry_for) {
|
||||||
|
$entry_for = ['seating', 'advancement'];
|
||||||
|
}
|
||||||
|
$entry_for = collect($entry_for);
|
||||||
|
$this->verifySubmission($student, $audition);
|
||||||
|
$entry = Entry::make([
|
||||||
|
'student_id' => $student->id,
|
||||||
|
'audition_id' => $audition->id,
|
||||||
|
'draw_number' => $this->checkDraw($audition),
|
||||||
|
'for_seating' => $entry_for->contains('seating'),
|
||||||
|
'for_advancement' => $entry_for->contains('advancement'),
|
||||||
|
]);
|
||||||
|
$entry->save();
|
||||||
|
|
||||||
|
return $entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function checkDraw(Audition $audition)
|
||||||
|
{
|
||||||
|
if (! $audition->hasFlag('drawn')) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// get the maximum value of draw_number from $audition->entries()
|
||||||
|
$draw_number = $audition->entries()->max('draw_number');
|
||||||
|
|
||||||
|
return $draw_number + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
private function verifySubmission(Student $student, Audition $audition): void
|
||||||
|
{
|
||||||
|
// Make sure it's a valid student
|
||||||
|
if (! $student->exists()) {
|
||||||
|
throw new CreateEntryException('Invalid student provided');
|
||||||
|
}
|
||||||
|
// Make sure the audition is valid
|
||||||
|
if (! $audition->exists()) {
|
||||||
|
throw new CreateEntryException('Invalid audition provided');
|
||||||
|
}
|
||||||
|
// A student can't enter the same audition twice
|
||||||
|
if (Entry::where('student_id', $student->id)->where('audition_id', $audition->id)->exists()) {
|
||||||
|
throw new CreateEntryException('That student is already entered in that audition');
|
||||||
|
}
|
||||||
|
// Can't enter a published audition
|
||||||
|
if ($audition->hasFlag('seats_published')) {
|
||||||
|
throw new CreateEntryException('Cannot add an entry to an audition where seats are published');
|
||||||
|
}
|
||||||
|
if ($audition->hasFlag('advancement_published')) {
|
||||||
|
throw new CreateEntryException('Cannot add an entry to an audition where advancement is published');
|
||||||
|
}
|
||||||
|
// Verify the grade of the student is in range for the audition
|
||||||
|
if ($student->grade > $audition->maximum_grade) {
|
||||||
|
throw new CreateEntryException('The grade of the student exceeds the maximum for that audition');
|
||||||
|
}
|
||||||
|
if ($student->grade < $audition->minimum_grade) {
|
||||||
|
throw new CreateEntryException('The grade of the student does not meet the minimum for that audition');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,9 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Exceptions;
|
||||||
|
|
||||||
|
use Exception;
|
||||||
|
|
||||||
|
class CreateEntryException extends Exception
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,127 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Actions\CreateEntry;
|
||||||
|
use App\Exceptions\CreateEntryException;
|
||||||
|
use App\Models\Audition;
|
||||||
|
use App\Models\Entry;
|
||||||
|
use App\Models\Student;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Support\Facades\App;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
beforeEach(function () {
|
||||||
|
$this->createEntry = App::make(CreateEntry::class);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('throws an exception if the student does not exist', function () {
|
||||||
|
$audition = Audition::factory()->create();
|
||||||
|
$student = Student::factory()->make();
|
||||||
|
$this->createEntry->__invoke($student, $audition);
|
||||||
|
})->throws(CreateEntryException::class, 'Invalid student provided');
|
||||||
|
it('throws an exception if the audition does not exist', function () {
|
||||||
|
$audition = Audition::factory()->make();
|
||||||
|
$student = Student::factory()->create();
|
||||||
|
$this->createEntry->__invoke($student, $audition);
|
||||||
|
})->throws(CreateEntryException::class, 'Invalid audition provided');
|
||||||
|
it('throws an exception if the student is already entered in the audition', function () {
|
||||||
|
// Arrange
|
||||||
|
$audition = Audition::factory()->create();
|
||||||
|
$student = Student::factory()->create();
|
||||||
|
$entry = Entry::create([
|
||||||
|
'student_id' => $student->id,
|
||||||
|
'audition_id' => $audition->id,
|
||||||
|
]);
|
||||||
|
// Act & Assert
|
||||||
|
$this->createEntry->createEntry($student, $audition);
|
||||||
|
})->throws(CreateEntryException::class, 'That student is already entered in that audition');
|
||||||
|
it('throws an exception if seats are published for the audition', function () {
|
||||||
|
// Arrange
|
||||||
|
$audition = Audition::factory()->create();
|
||||||
|
$student = Student::factory()->create();
|
||||||
|
$audition->addFlag('seats_published');
|
||||||
|
// Act & Assert
|
||||||
|
$this->createEntry->createEntry($student, $audition);
|
||||||
|
})->throws(CreateEntryException::class, 'Cannot add an entry to an audition where seats are published');
|
||||||
|
it('throws an exception if advancement is published for the audition', function () {
|
||||||
|
// Arrange
|
||||||
|
$audition = Audition::factory()->create();
|
||||||
|
$student = Student::factory()->create();
|
||||||
|
$audition->addFlag('advancement_published');
|
||||||
|
// Act & Assert
|
||||||
|
$this->createEntry->createEntry($student, $audition);
|
||||||
|
})->throws(CreateEntryException::class, 'Cannot add an entry to an audition where advancement is published');
|
||||||
|
it('throws an exception if the grade of the student exceeds the maximum grade for the audition', function () {
|
||||||
|
// Arrange
|
||||||
|
$audition = Audition::factory()->create(['minimum_grade' => 8, 'maximum_grade' => 9]);
|
||||||
|
$student = Student::factory()->create(['grade' => 11]);
|
||||||
|
// Act & Assert
|
||||||
|
$this->createEntry->createEntry($student, $audition);
|
||||||
|
})->throws(CreateEntryException::class, 'The grade of the student exceeds the maximum for that audition');
|
||||||
|
it('throws an exception if the grade of the student does not meet the minimum grade for the audition', function () {
|
||||||
|
// Arrange
|
||||||
|
$audition = Audition::factory()->create(['minimum_grade' => 8, 'maximum_grade' => 9]);
|
||||||
|
$student = Student::factory()->create(['grade' => 7]);
|
||||||
|
// Act & Assert
|
||||||
|
$this->createEntry->createEntry($student, $audition);
|
||||||
|
})->throws(CreateEntryException::class, 'The grade of the student does not meet the minimum for that audition');
|
||||||
|
it('returns an entry object', function () {
|
||||||
|
// Arrange
|
||||||
|
$audition = Audition::factory()->create(['minimum_grade' => 8, 'maximum_grade' => 9]);
|
||||||
|
$student = Student::factory()->create(['grade' => 8]);
|
||||||
|
// Act & Assert
|
||||||
|
$entry = $this->createEntry->createEntry($student, $audition);
|
||||||
|
expect($entry instanceof Entry)->toBeTrue();
|
||||||
|
});
|
||||||
|
it('creates an entry with a null draw number if the audition is not drawn', function () {
|
||||||
|
$audition = Audition::factory()->create(['minimum_grade' => 8, 'maximum_grade' => 9]);
|
||||||
|
$student = Student::factory()->create(['grade' => 8]);
|
||||||
|
// Act & Assert
|
||||||
|
$entry = $this->createEntry->createEntry($student, $audition);
|
||||||
|
expect($entry->draw_number)->toBeNull();
|
||||||
|
});
|
||||||
|
it('assigns the next highest draw_number available if the audition is drawn', function () {
|
||||||
|
$audition = Audition::factory()->create(['minimum_grade' => 8, 'maximum_grade' => 9]);
|
||||||
|
$student = Student::factory()->create(['grade' => 8]);
|
||||||
|
$audition->addFlag('drawn');
|
||||||
|
foreach (range(1, 5) as $number) {
|
||||||
|
Entry::factory()->create([
|
||||||
|
'audition_id' => $audition->id,
|
||||||
|
'draw_number' => $number,
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
$entry = $this->createEntry->createEntry($student, $audition);
|
||||||
|
expect($entry->draw_number)->toBe(6);
|
||||||
|
});
|
||||||
|
it('makes the entry for both seating and advancement if nothing is specified', function () {
|
||||||
|
$audition = Audition::factory()->create(['minimum_grade' => 8, 'maximum_grade' => 9]);
|
||||||
|
$student = Student::factory()->create(['grade' => 8]);
|
||||||
|
// Act & Assert
|
||||||
|
$entry = $this->createEntry->createEntry($student, $audition);
|
||||||
|
expect($entry->for_seating)->toBeTrue()
|
||||||
|
->and($entry->for_advancement)->toBeTrue();
|
||||||
|
});
|
||||||
|
it('makes the entry for only seating if only seating is specified', function () {
|
||||||
|
$audition = Audition::factory()->create(['minimum_grade' => 8, 'maximum_grade' => 9]);
|
||||||
|
$student = Student::factory()->create(['grade' => 8]);
|
||||||
|
// Act & Assert
|
||||||
|
$entry = $this->createEntry->createEntry($student, $audition, 'seating');
|
||||||
|
expect($entry->for_seating)->toBeTrue()
|
||||||
|
->and($entry->for_advancement)->toBeFalse();
|
||||||
|
});
|
||||||
|
it('makes the entry for only advancement if only advancement is specified', function () {
|
||||||
|
$audition = Audition::factory()->create(['minimum_grade' => 8, 'maximum_grade' => 9]);
|
||||||
|
$student = Student::factory()->create(['grade' => 8]);
|
||||||
|
// Act & Assert
|
||||||
|
$entry = $this->createEntry->createEntry($student, $audition, 'advancement');
|
||||||
|
expect($entry->for_seating)->toBeFalse()
|
||||||
|
->and($entry->for_advancement)->toBeTrue();
|
||||||
|
});
|
||||||
|
it('makes the entry for both seating and advancement if both are specified', function () {
|
||||||
|
$audition = Audition::factory()->create(['minimum_grade' => 8, 'maximum_grade' => 9]);
|
||||||
|
$student = Student::factory()->create(['grade' => 8]);
|
||||||
|
// Act & Assert
|
||||||
|
$entry = $this->createEntry->createEntry($student, $audition, ['seating', 'advancement']);
|
||||||
|
expect($entry->for_seating)->toBeTrue()
|
||||||
|
->and($entry->for_advancement)->toBeTrue();
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue