auditionadmin/app/Actions/Entries/DoublerDecision.php

96 lines
3.5 KiB
PHP

<?php
namespace App\Actions\Entries;
use App\Exceptions\AuditionAdminException;
use App\Models\Doubler;
use App\Models\Entry;
use Illuminate\Support\Facades\Cache;
class DoublerDecision
{
/**
* @throws AuditionAdminException
*/
public function __invoke(Entry $entry, string $decision): void
{
$this->doublerDecision($entry, $decision);
}
/**
* @throws AuditionAdminException
*/
public function doublerDecision(Entry $entry, string $decision): void
{
match ($decision) {
'accept' => $this->accept($entry),
'decline' => $this->decline($entry),
default => throw new AuditionAdminException('Invalid decision specified')
};
}
/**
* Accepts an entry for the given audition.
*
* This method ensures the entry is not already declined, and that the
* audition is not in a state where seats or advancement are published.
* If the entry is already declined, this method does nothing.
* If the audition is in a state where seats or advancement are published,
* this method throws an exception.
*
* This method also declines all other entries in the same audition,
* clearing the rank cache for the audition.
*
* @throws AuditionAdminException
*/
public function accept(Entry $entry): void
{
if ($entry->hasFlag('declined')) {
throw new AuditionAdminException('Entry '.$entry->id.' is already declined');
}
if ($entry->audition->hasFlag('seats_published')) {
throw new AuditionAdminException('Cannot accept an entry in an audition where seats are published');
}
Cache::forget('rank_seating_'.$entry->audition_id);
// Process student entries
$doublerData = Doubler::findDoubler($entry->student_id, $entry->audition->event_id);
// Check each entry and see if it is unscored. We can't accept this entry if that is the case.
foreach ($doublerData->entries() as $doublerEntry) {
if (! $doublerEntry->totalScore && ! $doublerEntry->hasFlag('declined') && ! $doublerEntry->hasFlag('no_show') && ! $doublerEntry->hasFlag('failed_prelim')) {
throw new AuditionAdminException('Cannot accept seating for '.$entry->student->full_name().' because student has unscored entries');
}
}
// Decline all other entries
foreach ($doublerData->entries() as $doublerEntry) {
Cache::forget('rank_seating_'.$doublerEntry->audition_id);
if ($doublerEntry->id !== $entry->id && ! $doublerEntry->hasFlag('no_show') && ! $doublerEntry->hasFlag('failed_prelim') && ! $doublerEntry->hasFlag('declined')) {
$this->decline($doublerEntry);
}
}
}
/**
* @throws AuditionAdminException
*/
public function decline($entry): void
{
// Entry cannot decline a seat twice
if ($entry->hasFlag('declined')) {
throw new AuditionAdminException('Entry '.$entry->id.' is already declined');
}
if (! $entry->totalScore) {
throw new AuditionAdminException('Cannot decline an unscored entry');
}
if ($entry->audition->hasFlag('seats_published')) {
throw new AuditionAdminException('Cannot decline an entry in an audition where seats are published');
}
// Flag this entry
$entry->addFlag('declined');
// Clear rank cache
Cache::forget('rank_seating_'.$entry->audition_id);
}
}