Rewrite DoublerDecision action.

Rewrite SeatAuditionFormController to use the action for making doubler decisions.
This commit is contained in:
Matt Young 2025-06-30 18:26:12 -05:00
parent 3a1b03a6c7
commit 0d8d876ba7
2 changed files with 75 additions and 44 deletions

View File

@ -3,19 +3,12 @@
namespace App\Actions\Entries;
use App\Exceptions\AuditionAdminException;
use App\Models\Doubler;
use App\Models\Entry;
use App\Services\DoublerService;
use Illuminate\Support\Facades\Cache;
class DoublerDecision
{
protected DoublerService $doublerService;
public function __construct(DoublerService $doublerService)
{
$this->doublerService = $doublerService;
}
/**
* @throws AuditionAdminException
*/
@ -41,18 +34,46 @@ class DoublerDecision
}
/**
* 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
{
Cache::forget('audition'.$entry->audition_id.'seating');
Cache::forget('audition'.$entry->audition_id.'advancement');
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');
}
if ($entry->audition->hasFlag('advancement_published')) {
throw new AuditionAdminException('Cannot accept an entry in an audition where advancement is published');
}
Cache::forget('rank_seating_'.$entry->audition_id);
// Decline all other entries and clear rank cache
$doublerInfo = $this->doublerService->simpleDoubleInfo($entry);
foreach ($doublerInfo as $doublerEntry) {
Cache::forget('audition'.$doublerEntry->audition_id.'seating');
/** @var Entry $doublerEntry */
if ($doublerEntry->id !== $entry->id) {
$doublerEntry->addFlag('declined');
// 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);
}
}
}
@ -62,12 +83,14 @@ class DoublerDecision
*/
public function decline($entry): void
{
Cache::forget('audition'.$entry->audition_id.'seating');
Cache::forget('audition'.$entry->audition_id.'advancement');
// Entry cannot decline a seat twice
if ($entry->hasFlag('declined')) {
throw new AuditionAdminException('Entry is already declined');
throw new AuditionAdminException('Entry '.$entry->id.' is already declined');
}
Cache::forget('audition'.$entry->audition_id.'seating');
// Flag this entry
$entry->addFlag('declined');
// Clear rank cache
Cache::forget('rank_seating_'.$entry->audition_id);
}
}

View File

@ -131,12 +131,18 @@ class SeatAuditionFormController extends Controller
public function massDecline(Audition $audition)
{
$decider = app(DoublerDecision::class);
$validData = request()->validate([
'decline-below' => ['required', 'integer', 'min:0'],
]);
$ranker = app(RankAuditionEntries::class);
// Get scored entries in order
$scored_entries = $ranker($audition, 'seating');
try {
$scored_entries = $ranker($audition, 'seating');
} catch (AuditionAdminException $e) {
return redirect()->route('seating.audition', ['audition' => $audition->id])
->with('error', $e->getMessage());
}
$scored_entries->load(['student.doublers', 'student.school']);
foreach ($scored_entries as $entry) {
Debugbar::info('Starting entry '.$entry->student->full_name());
@ -160,30 +166,27 @@ class SeatAuditionFormController extends Controller
continue;
}
$entry->addFlag('declined');
try {
$decider->decline($entry);
} catch (AuditionAdminException $e) {
return redirect()->route('seating.audition', ['audition' => $audition->id])
->with('error', $e->getMessage());
}
}
Cache::forget('rank_seating_'.$entry->audition_id);
Cache::forget('rank_seating_'.$audition->id);
return redirect()->route('seating.audition', ['audition' => $audition->id]);
}
public function acceptSeat(
Audition $audition,
Entry $entry
) {
$doublerData = Doubler::findDoubler($entry->student_id, $audition->event_id);
foreach ($doublerData->entries() as $doublerEntry) {
if (! $doublerEntry->totalScore && ! $doublerEntry->hasFlag('declined') && ! $doublerEntry->hasFlag('no_show') && ! $doublerEntry->hasFlag('failed_prelim')) {
return redirect()->route('seating.audition', ['audition' => $audition->id])->with('error',
'Cannot accept seating for '.$entry->student->full_name().' because student has unscored 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')) {
$doublerEntry->addFlag('declined');
}
public function acceptSeat(Audition $audition, Entry $entry)
{
$decider = app(DoublerDecision::class);
try {
$decider->accept($entry);
} catch (AuditionAdminException $e) {
return redirect()->route('seating.audition', ['audition' => $audition->id])
->with('error', $e->getMessage());
}
return redirect()->route('seating.audition', ['audition' => $audition->id])->with('success',
@ -214,15 +217,20 @@ class SeatAuditionFormController extends Controller
'ensemble.*' => ['required', 'integer', 'min:0'],
]);
$proposedSeatingArray = [];
$rankedEntries = $ranker($audition, 'seating');
try {
$rankedEntries = $ranker($audition, 'seating');
} catch (AuditionAdminException $e) {
return redirect()->route('seating.audition', ['audition' => $audition->id])
->with('error', $e->getMessage());
}
$rankedEntries = $rankedEntries->reject(function ($entry) {
return $entry->hasFlag('declined');
});
$rankedEntries->load(['student.school']);
$rankedEnembles = Ensemble::orderBy('rank')->where('event_id', $audition->event_id)->get();
$rankedEnsembles = Ensemble::orderBy('rank')->where('event_id', $audition->event_id)->get();
$ensembleRankOn = 1;
foreach ($rankedEnembles as $ensemble) {
foreach ($rankedEnsembles as $ensemble) {
if (! Arr::has($validated['ensemble'], $ensemble->id)) {
continue;
}
@ -245,7 +253,7 @@ class SeatAuditionFormController extends Controller
$ensembleRankOn++;
}
$sessionKeyName = 'proposedSeatingArray-'.$audition->id;
$request->session()->put($sessionKeyName, $proposedSeatingArray, 10);
$request->session()->put($sessionKeyName, $proposedSeatingArray);
return redirect()->route('seating.audition', ['audition' => $audition->id]);
}