Add scopes to models #10

Merged
okorpheus merged 5 commits from add-scopes-to-models into master 2024-07-01 04:00:24 +00:00
4 changed files with 94 additions and 4 deletions
Showing only changes of commit 3acc478143 - Show all commits

View File

@ -2,6 +2,7 @@
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
@ -69,7 +70,7 @@ class Entry extends Model
}
public function addFlag($flag)
public function addFlag($flag): void
{
if ($this->hasFlag($flag)) {
return;
@ -78,7 +79,7 @@ class Entry extends Model
$this->flags()->create(['flag_name' => $flag]);
}
public function removeFlag($flag)
public function removeFlag($flag): void
{
// remove related auditionFlag where flag_name = $flag
$this->flags()->where('flag_name', $flag)->delete();
@ -100,4 +101,23 @@ class Entry extends Model
{
return $this->hasOne(Seat::class);
}
public function scopeForSeating(Builder $query): void
{
$query->where('for_seating', 1);
}
public function scopeForAdvancement(Builder $query): void
{
$query->where('for_advancement', 1);
}
public function scopeAvailable(Builder $query): void
{
$query->whereDoesntHave('flags', function (Builder $query) {
$query->where('flag_name', 'declined')
->orWhere('flag_name', 'no-show')
->orWhere('flag_name', 'failed-prelim');
});
}
}

View File

@ -2,6 +2,8 @@
namespace Database\Factories;
use App\Models\Audition;
use App\Models\Student;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
@ -16,9 +18,28 @@ class EntryFactory extends Factory
*/
public function definition(): array
{
$student = Student::factory()->create();
$audition = Audition::factory()->create();
return [
'student_id' => 3,
'audition_id' =>3
'student_id' => $student->id,
'audition_id' => $audition->id,
'draw_number' => null,
'for_seating' => 1,
'for_advancement' => 1,
];
}
public function seatingOnly(): self
{
return $this->state(
fn (array $attributes) => ['for_advancement' => 0]
);
}
public function advanceOnly(): self
{
return $this->state(
fn (array $attributes) => ['for_seating' => 0]
);
}
}

View File

@ -2,6 +2,7 @@
namespace Database\Factories;
use App\Models\School;
use Illuminate\Database\Eloquent\Factories\Factory;
/**
@ -16,7 +17,9 @@ class StudentFactory extends Factory
*/
public function definition(): array
{
$school = School::factory()->create();
return [
'school_id' => $school->id,
'first_name' => fake()->firstName(),
'last_name' => fake()->lastName(),
'grade' => rand(7,12),

View File

@ -0,0 +1,46 @@
<?php
use App\Models\Entry;
use Illuminate\Foundation\Testing\RefreshDatabase;
uses(RefreshDatabase::class);
it('only returns entries for seating with forSeating scope', function () {
// Arrange
Entry::factory()->advanceOnly()->create();
$seatingEntry = Entry::factory()->create();
// Act & Assert
expect(Entry::forSeating()->get())
->toHaveCount(1)
->first()->id->toEqual($seatingEntry->id);
});
it('only returns entries for advancement with for forAdvancement scope', function () {
// Arrange
Entry::factory()->seatingOnly()->create();
$advancementEntry = Entry::factory()->create();
// Act & Assert
expect(Entry::forAdvancement()->get())
->toHaveCount(1)
->first()->id->toEqual($advancementEntry->id);
});
it('only returns entries that do not have a declined, no-show, or failed-prelim flag with available scope',
function () {
// Arrange
$availableEntry = Entry::factory()->create();
$declinedEntry = Entry::factory()->create();
$noShowEntry = Entry::factory()->create();
$failedPrelimEntry = Entry::factory()->create();
$declinedEntry->addFlag('declined');
$noShowEntry->addFlag('no-show');
$failedPrelimEntry->addFlag('failed-prelim');
// Act & Assert
expect(Entry::available()->get())
->toHaveCount(1)
->first()->id->toEqual($availableEntry->id);
});