Merge pull request #13 from okorpheus/enter-and-store-no-show
Enter and store no show
This commit is contained in:
commit
2779bd5f88
|
|
@ -0,0 +1,11 @@
|
||||||
|
<component name="ProjectRunConfigurationManager">
|
||||||
|
<configuration default="false" name="tests - paralell" type="PestRunConfigurationType">
|
||||||
|
<option name="pestRunnerSettings">
|
||||||
|
<PestRunner directory="$PROJECT_DIR$/tests" method="" options="--parallel --recreate-databases" />
|
||||||
|
</option>
|
||||||
|
<option name="runnerSettings">
|
||||||
|
<PhpTestRunnerSettings directory="$PROJECT_DIR$/tests" method="" options="--parallel --recreate-databases" />
|
||||||
|
</option>
|
||||||
|
<method v="2" />
|
||||||
|
</configuration>
|
||||||
|
</component>
|
||||||
|
|
@ -181,37 +181,4 @@ class AuditionController extends Controller
|
||||||
|
|
||||||
return to_route('admin.auditions.index')->with('success', 'Audition deleted successfully');
|
return to_route('admin.auditions.index')->with('success', 'Audition deleted successfully');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function prepareDraw()
|
|
||||||
{
|
|
||||||
if (! Auth::user()->is_admin) {
|
|
||||||
abort(403);
|
|
||||||
}
|
|
||||||
$allAuditions = Audition::with('entries')->orderBy('score_order')->get();
|
|
||||||
$nodraw_auditions = $allAuditions->filter(function ($audition) {
|
|
||||||
return $audition->has_no_draw();
|
|
||||||
});
|
|
||||||
$drawn_auditions = $allAuditions->filter(function ($audition) {
|
|
||||||
return $audition->has_complete_draw();
|
|
||||||
});
|
|
||||||
$partial_draw_auditions = $allAuditions->filter(function ($audition) {
|
|
||||||
return $audition->has_partial_draw();
|
|
||||||
});
|
|
||||||
|
|
||||||
return view('admin.entries.prepare_draw',
|
|
||||||
compact('nodraw_auditions', 'drawn_auditions', 'partial_draw_auditions'));
|
|
||||||
}
|
|
||||||
|
|
||||||
public function runDraw(Request $request)
|
|
||||||
{
|
|
||||||
if (! Auth::user()->is_admin) {
|
|
||||||
abort(403);
|
|
||||||
}
|
|
||||||
$draw_auditions = Audition::with('entries')->find(array_keys($request->input('auditions')));
|
|
||||||
foreach ($draw_auditions as $audition) {
|
|
||||||
$audition->runDraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
return redirect(' / admin / auditions / run_draw');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,10 +6,8 @@ use App\Http\Controllers\Controller;
|
||||||
use App\Models\Audition;
|
use App\Models\Audition;
|
||||||
use App\Models\School;
|
use App\Models\School;
|
||||||
use App\Models\Student;
|
use App\Models\Student;
|
||||||
use Illuminate\Http\Request;
|
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
use Illuminate\Support\Facades\Log;
|
|
||||||
use function abort;
|
use function abort;
|
||||||
use function to_route;
|
use function to_route;
|
||||||
use function view;
|
use function view;
|
||||||
|
|
@ -50,7 +48,7 @@ class StudentController extends Controller
|
||||||
'school_id' => ['required', 'exists:schools,id'],
|
'school_id' => ['required', 'exists:schools,id'],
|
||||||
]);
|
]);
|
||||||
|
|
||||||
$student = Student::create([
|
Student::create([
|
||||||
'first_name' => request('first_name'),
|
'first_name' => request('first_name'),
|
||||||
'last_name' => request('last_name'),
|
'last_name' => request('last_name'),
|
||||||
'grade' => request('grade'),
|
'grade' => request('grade'),
|
||||||
|
|
@ -69,11 +67,12 @@ class StudentController extends Controller
|
||||||
$maxGrade = Audition::max('maximum_grade');
|
$maxGrade = Audition::max('maximum_grade');
|
||||||
$schools = School::orderBy('name')->get();
|
$schools = School::orderBy('name')->get();
|
||||||
$student->loadCount('entries');
|
$student->loadCount('entries');
|
||||||
|
|
||||||
return view('admin.students.edit',
|
return view('admin.students.edit',
|
||||||
['student' => $student, 'schools' => $schools, 'minGrade' => $minGrade, 'maxGrade' => $maxGrade]);
|
['student' => $student, 'schools' => $schools, 'minGrade' => $minGrade, 'maxGrade' => $maxGrade]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function update(Request $request, Student $student)
|
public function update(Student $student)
|
||||||
{
|
{
|
||||||
if (! Auth::user()->is_admin) {
|
if (! Auth::user()->is_admin) {
|
||||||
abort(403);
|
abort(403);
|
||||||
|
|
@ -105,8 +104,7 @@ class StudentController extends Controller
|
||||||
|
|
||||||
public function destroy(Student $student)
|
public function destroy(Student $student)
|
||||||
{
|
{
|
||||||
Log::debug('Deleting student '.$student->id);
|
if ($student->entries()->count() > 0) {
|
||||||
if($student->entries()->count() > 0) {
|
|
||||||
return to_route('admin.students.index')->with('error', 'You cannot delete a student with entries.');
|
return to_route('admin.students.index')->with('error', 'You cannot delete a student with entries.');
|
||||||
}
|
}
|
||||||
$name = $student->full_name();
|
$name = $student->full_name();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,103 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Tabulation;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Models\Entry;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
use function to_route;
|
||||||
|
|
||||||
|
class EntryFlagController extends Controller
|
||||||
|
{
|
||||||
|
public function noShowSelect()
|
||||||
|
{
|
||||||
|
$method = 'GET';
|
||||||
|
$formRoute = 'entry-flags.confirmNoShow';
|
||||||
|
|
||||||
|
return view('tabulation.choose_entry', compact('method', 'formRoute'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function noShowConfirm(Request $request)
|
||||||
|
{
|
||||||
|
$validData = $request->validate([
|
||||||
|
'entry_id' => 'required|exists:entries,id',
|
||||||
|
]);
|
||||||
|
$entry = Entry::with('flags')->withCount('scoreSheets')->find($validData['entry_id']);
|
||||||
|
|
||||||
|
// If any results are published, get gone
|
||||||
|
if ($entry->audition->hasFlag('seats_published')) {
|
||||||
|
return to_route('entry-flags.noShowSelect')->with('error',
|
||||||
|
'Cannot enter a no-show for an entry in an audition where seats are published');
|
||||||
|
}
|
||||||
|
if ($entry->audition->hasFlag('advance_published')) {
|
||||||
|
return to_route('entry-flags.noShowSelect')->with('error',
|
||||||
|
'Cannot enter a no-show for an entry in an audition where advancement is published');
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($entry->hasFlag('no_show')) {
|
||||||
|
$formId = 'no-show-cancellation-form';
|
||||||
|
$buttonName = 'Remove No Show';
|
||||||
|
$submitRouteName = 'entry-flags.undoNoShow';
|
||||||
|
$cardHeading = 'Undo No-Show';
|
||||||
|
$method = 'DELETE';
|
||||||
|
} else {
|
||||||
|
$formId = 'no-show-confirmation-form';
|
||||||
|
$buttonName = 'Confirm No Show';
|
||||||
|
$submitRouteName = 'entry-flags.enterNoShow';
|
||||||
|
$cardHeading = 'Confirm No-Show';
|
||||||
|
$method = 'POST';
|
||||||
|
}
|
||||||
|
$scores = [];
|
||||||
|
if ($entry->score_sheets_count > 0) {
|
||||||
|
$scores = $entry->scoreSheets;
|
||||||
|
$scores->load('judge');
|
||||||
|
}
|
||||||
|
|
||||||
|
return view('tabulation.no_show_confirm',
|
||||||
|
compact('entry',
|
||||||
|
'formId',
|
||||||
|
'buttonName',
|
||||||
|
'submitRouteName',
|
||||||
|
'cardHeading',
|
||||||
|
'method',
|
||||||
|
'scores'));
|
||||||
|
}
|
||||||
|
|
||||||
|
public function enterNoShow(Entry $entry)
|
||||||
|
{
|
||||||
|
if ($entry->audition->hasFlag('seats_published')) {
|
||||||
|
return to_route('entry-flags.noShowSelect')->with('error',
|
||||||
|
'Cannot enter a no-show for an entry in an audition where seats are published');
|
||||||
|
}
|
||||||
|
if ($entry->audition->hasFlag('advance_published')) {
|
||||||
|
return to_route('entry-flags.noShowSelect')->with('error',
|
||||||
|
'Cannot enter a no-show for an entry in an audition where advancement is published');
|
||||||
|
}
|
||||||
|
DB::table('score_sheets')->where('entry_id', $entry->id)->delete();
|
||||||
|
|
||||||
|
$entry->addFlag('no_show');
|
||||||
|
|
||||||
|
$msg = 'No Show has been entered for '.$entry->audition->name.' #'.$entry->draw_number.' (ID: '.$entry->id.').';
|
||||||
|
|
||||||
|
return to_route('entry-flags.noShowSelect')->with('success', $msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function undoNoShow(Entry $entry)
|
||||||
|
{
|
||||||
|
if ($entry->audition->hasFlag('seats_published')) {
|
||||||
|
return to_route('entry-flags.noShowSelect')->with('error',
|
||||||
|
'Cannot undo a no-show for an entry in an audition where seats are published');
|
||||||
|
}
|
||||||
|
if ($entry->audition->hasFlag('advance_published')) {
|
||||||
|
return to_route('entry-flags.noShowSelect')->with('error',
|
||||||
|
'Cannot undo a no-show for an entry in an audition where advancement is published');
|
||||||
|
}
|
||||||
|
|
||||||
|
$entry->removeFlag('no_show');
|
||||||
|
|
||||||
|
return to_route('entry-flags.noShowSelect')->with('success',
|
||||||
|
'No Show status has been removed for '.$entry->audition->name.' #'.$entry->draw_number.' (ID: '.$entry->id.').');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -7,36 +7,44 @@ use App\Models\Entry;
|
||||||
use App\Models\ScoreSheet;
|
use App\Models\ScoreSheet;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Session;
|
use Illuminate\Support\Facades\Session;
|
||||||
|
|
||||||
class ScoreController extends Controller
|
class ScoreController extends Controller
|
||||||
{
|
{
|
||||||
public function chooseEntry(Request $request)
|
public function chooseEntry(Request $request)
|
||||||
{
|
{
|
||||||
return view('tabulation.choose_entry');
|
$method = 'GET';
|
||||||
|
$formRoute = 'scores.entryScoreSheet';
|
||||||
|
|
||||||
|
return view('tabulation.choose_entry', compact('method', 'formRoute'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function destroyScore(ScoreSheet $score) {
|
public function destroyScore(ScoreSheet $score)
|
||||||
|
{
|
||||||
$score->delete();
|
$score->delete();
|
||||||
return redirect()->back()->with('success','Score Deleted');
|
|
||||||
|
return redirect()->back()->with('success', 'Score Deleted');
|
||||||
}
|
}
|
||||||
|
|
||||||
public function entryScoreSheet(Request $request)
|
public function entryScoreSheet(Request $request)
|
||||||
{
|
{
|
||||||
$existing_sheets = [];
|
$existing_sheets = [];
|
||||||
$entry = Entry::with(['student','audition.room.judges'])->find($request->input('entry_id'));
|
$entry = Entry::with(['student', 'audition.room.judges'])->find($request->input('entry_id'));
|
||||||
$judges = $entry->audition->room->judges;
|
$judges = $entry->audition->room->judges;
|
||||||
foreach ($judges as $judge) {
|
foreach ($judges as $judge) {
|
||||||
$scoreSheet = ScoreSheet::where('entry_id',$entry->id)->where('user_id',$judge->id)->first();
|
$scoreSheet = ScoreSheet::where('entry_id', $entry->id)->where('user_id', $judge->id)->first();
|
||||||
if ($scoreSheet) {
|
if ($scoreSheet) {
|
||||||
Session::flash('caution','Scores exist for this entry. Now editing existing scores');
|
Session::flash('caution', 'Scores exist for this entry. Now editing existing scores');
|
||||||
$existing_sheets[$judge->id] = $scoreSheet;
|
$existing_sheets[$judge->id] = $scoreSheet;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$scoring_guide = $entry->audition->scoringGuide;
|
$scoring_guide = $entry->audition->scoringGuide;
|
||||||
$subscores = $entry->audition->scoringGuide->subscores->sortBy('display_order');
|
$subscores = $entry->audition->scoringGuide->subscores->sortBy('display_order');
|
||||||
if (!$entry) {
|
if (! $entry) {
|
||||||
return redirect()->route('tabulation.chooseEntry')->with('error','Entry not found');
|
return redirect()->route('tabulation.chooseEntry')->with('error', 'Entry not found');
|
||||||
}
|
}
|
||||||
return view('tabulation.entry_score_sheet', compact('entry','judges','scoring_guide','subscores','existing_sheets'));
|
|
||||||
|
return view('tabulation.entry_score_sheet',
|
||||||
|
compact('entry', 'judges', 'scoring_guide', 'subscores', 'existing_sheets'));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function saveEntryScoreSheet(Request $request, Entry $entry)
|
public function saveEntryScoreSheet(Request $request, Entry $entry)
|
||||||
|
|
@ -52,16 +60,17 @@ class ScoreController extends Controller
|
||||||
|
|
||||||
$scoreValidation = $scoringGuide->validateScores($request->input('judge'.$judge->id));
|
$scoreValidation = $scoringGuide->validateScores($request->input('judge'.$judge->id));
|
||||||
if ($scoreValidation != 'success') {
|
if ($scoreValidation != 'success') {
|
||||||
return redirect(url()->previous())->with('error', $judge->full_name() . ': ' . $scoreValidation)->with('oldScores',$request->all());
|
return redirect(url()->previous())->with('error',
|
||||||
|
$judge->full_name().': '.$scoreValidation)->with('oldScores', $request->all());
|
||||||
}
|
}
|
||||||
|
|
||||||
$scoreSubmission = $request->input('judge'.$judge->id);
|
$scoreSubmission = $request->input('judge'.$judge->id);
|
||||||
$scoresToSave = [];
|
$scoresToSave = [];
|
||||||
foreach ($subscores as $subscore) {
|
foreach ($subscores as $subscore) {
|
||||||
$scoresToSave[$subscore->id] = [
|
$scoresToSave[$subscore->id] = [
|
||||||
'subscore_id'=>$subscore->id,
|
'subscore_id' => $subscore->id,
|
||||||
'subscore_name' => $subscore->name,
|
'subscore_name' => $subscore->name,
|
||||||
'score' => intval($scoreSubmission[$subscore->id])
|
'score' => intval($scoreSubmission[$subscore->id]),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
$preparedScoreSheets[$judge->id]['scores'] = $scoresToSave;
|
$preparedScoreSheets[$judge->id]['scores'] = $scoresToSave;
|
||||||
|
|
@ -72,7 +81,7 @@ class ScoreController extends Controller
|
||||||
['subscores' => $sheet['scores']]
|
['subscores' => $sheet['scores']]
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return redirect()->route('scores.chooseEntry')->with('success',count($preparedScoreSheets) . " Scores saved");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return redirect()->route('scores.chooseEntry')->with('success', count($preparedScoreSheets).' Scores saved');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -25,7 +25,7 @@ class CheckIfCanTab
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
|
|
||||||
return redirect('/')->with('error', 'You do not have access to score tabulation.');
|
return redirect('dashboard')->with('error', 'You are not authorized to perform this action');
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,14 +16,6 @@ class Audition extends Model
|
||||||
|
|
||||||
protected $guarded = [];
|
protected $guarded = [];
|
||||||
|
|
||||||
protected $rankedEntries = null;
|
|
||||||
|
|
||||||
protected static $completeAuditions = null;
|
|
||||||
|
|
||||||
protected $fully_scored; // Set by TabulationService
|
|
||||||
|
|
||||||
protected $scored_entries_count; //Set by TabulationService
|
|
||||||
|
|
||||||
public function event(): BelongsTo
|
public function event(): BelongsTo
|
||||||
{
|
{
|
||||||
return $this->belongsTo(Event::class);
|
return $this->belongsTo(Event::class);
|
||||||
|
|
@ -49,84 +41,6 @@ class Audition extends Model
|
||||||
return '$'.number_format($this->entry_fee / 100, 2);
|
return '$'.number_format($this->entry_fee / 100, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function has_no_draw(): bool
|
|
||||||
{
|
|
||||||
// return true if all of my entries have a null draw_number
|
|
||||||
//return $this->entries->every(fn($entry) => is_null($entry->draw_number));
|
|
||||||
// return $this->entries()->whereNotNull('draw_number')->doesntExist();
|
|
||||||
if ($this->entries->count() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($this->relationLoaded('entries')) {
|
|
||||||
return $this->entries->every(function ($entry) {
|
|
||||||
return is_null($entry->draw_number);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return $this->entries()->whereNotNull('draw_number')->doesntExist();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
public function has_complete_draw(): bool
|
|
||||||
{
|
|
||||||
// return true if all of my entries have a draw_number
|
|
||||||
// return $this->entries->every(fn($entry) => !is_null($entry->draw_number));
|
|
||||||
// return $this->entries()->whereNull('draw_number')->doesntExist();
|
|
||||||
if ($this->entries->count() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if ($this->relationLoaded('entries')) {
|
|
||||||
return $this->entries->every(function ($entry) {
|
|
||||||
return ! is_null($entry->draw_number);
|
|
||||||
});
|
|
||||||
} else {
|
|
||||||
return $this->entries()->whereNull('draw_number')->doesntExist();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function has_partial_draw(): bool
|
|
||||||
{
|
|
||||||
if ($this->entries->count() == 0) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
// return true I have at least one entry with a null draw number AND at least one entry with a non-null draw number
|
|
||||||
//return $this->entries->contains(fn($entry) => is_null($entry->draw_number)) && $this->entries->contains(fn($entry) => !is_null($entry->draw_number));
|
|
||||||
|
|
||||||
//$hasNull = $this->entries()->whereNull('draw_number')->exists();
|
|
||||||
//$hasNotNull = $this->entries()->whereNotNull('draw_number')->exists();
|
|
||||||
//return $hasNull && $hasNotNull;
|
|
||||||
|
|
||||||
if ($this->relationLoaded('entries')) {
|
|
||||||
$hasNull = $this->entries->contains(function ($entry) {
|
|
||||||
return is_null($entry->draw_number);
|
|
||||||
});
|
|
||||||
|
|
||||||
$hasNotNull = $this->entries->contains(function ($entry) {
|
|
||||||
return ! is_null($entry->draw_number);
|
|
||||||
});
|
|
||||||
|
|
||||||
return $hasNull && $hasNotNull;
|
|
||||||
} else {
|
|
||||||
$hasNull = $this->entries()->whereNull('draw_number')->exists();
|
|
||||||
$hasNotNull = $this->entries()->whereNotNull('draw_number')->exists();
|
|
||||||
|
|
||||||
return $hasNull && $hasNotNull;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public function runDraw(): null
|
|
||||||
{
|
|
||||||
$entries = $this->entries->shuffle();
|
|
||||||
|
|
||||||
foreach ($entries as $index => $entry) {
|
|
||||||
$entry->update(['draw_number' => $index + 1]);
|
|
||||||
$entry->save();
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
// TODO move all draw functions to a DrawService
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return BelongsToMany|User[]
|
* @return BelongsToMany|User[]
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,12 @@
|
||||||
|
|
||||||
namespace Database\Factories;
|
namespace Database\Factories;
|
||||||
|
|
||||||
|
use App\Models\Ensemble;
|
||||||
|
use App\Models\Event;
|
||||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @extends \Illuminate\Database\Eloquent\Factories\Factory<\App\Models\Ensemble>
|
* @extends Factory<Ensemble>
|
||||||
*/
|
*/
|
||||||
class EnsembleFactory extends Factory
|
class EnsembleFactory extends Factory
|
||||||
{
|
{
|
||||||
|
|
@ -17,8 +19,8 @@ class EnsembleFactory extends Factory
|
||||||
public function definition(): array
|
public function definition(): array
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => $this->faker->name,
|
'name' => $this->faker->words(4, true),
|
||||||
'event_id' => \App\Models\Event::factory(),
|
'event_id' => Event::factory(),
|
||||||
'code' => $this->faker->randomLetter().$this->faker->randomLetter,
|
'code' => $this->faker->randomLetter().$this->faker->randomLetter,
|
||||||
'rank' => $this->faker->numberBetween(1, 10),
|
'rank' => $this->faker->numberBetween(1, 10),
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ namespace Database\Seeders;
|
||||||
|
|
||||||
use App\Models\ScoreSheet;
|
use App\Models\ScoreSheet;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
|
|
||||||
use Illuminate\Database\Seeder;
|
use Illuminate\Database\Seeder;
|
||||||
|
|
||||||
class ScoreAllAuditions extends Seeder
|
class ScoreAllAuditions extends Seeder
|
||||||
|
|
@ -16,23 +15,23 @@ class ScoreAllAuditions extends Seeder
|
||||||
{
|
{
|
||||||
$judges = User::all();
|
$judges = User::all();
|
||||||
foreach ($judges as $judge) {
|
foreach ($judges as $judge) {
|
||||||
foreach( $judge->rooms as $room) {
|
foreach ($judge->rooms as $room) {
|
||||||
foreach ($room->auditions as $audition){
|
foreach ($room->auditions as $audition) {
|
||||||
$scoringGuide = $audition->scoringGuide;
|
$scoringGuide = $audition->scoringGuide;
|
||||||
$subscores = $scoringGuide->subscores;
|
$subscores = $scoringGuide->subscores;
|
||||||
foreach ($audition->entries as $entry){
|
foreach ($audition->entries as $entry) {
|
||||||
$scoreArray = [];
|
$scoreArray = [];
|
||||||
foreach ($subscores as $subscore) {
|
foreach ($subscores as $subscore) {
|
||||||
$scoreArray[$subscore->id] = [
|
$scoreArray[$subscore->id] = [
|
||||||
'score' => mt_rand(0,100),
|
'score' => mt_rand(0, 100),
|
||||||
'subscore_id' => $subscore->id,
|
'subscore_id' => $subscore->id,
|
||||||
'subscore_name' => $subscore->name
|
'subscore_name' => $subscore->name,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
ScoreSheet::create([
|
ScoreSheet::create([
|
||||||
'user_id' => $judge->id,
|
'user_id' => $judge->id,
|
||||||
'entry_id' => $entry->id,
|
'entry_id' => $entry->id,
|
||||||
'subscores' => $scoreArray
|
'subscores' => $scoreArray,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
<div x-data="{ toggle: {{ $checked ? 'true':'false'}} }" class="flex items-center">
|
<div x-data="{ toggle: {{ $checked ? 'true':'false'}} }" class="flex items-center">
|
||||||
<label {{ $attributes->merge(['class'=>'relative inline-flex items-center cursor-pointer']) }}>{{ $slot }}
|
<label {{ $attributes->merge(['class'=>'relative inline-flex items-center cursor-pointer']) }}>{{ $slot }}
|
||||||
<input type="checkbox" x-model="toggle" name="{{ $name }}" class="sr-only" {{ $checked ? 'checked':''}} value="1" >
|
<input type="checkbox" x-model="toggle" name="{{ $name }}" class="sr-only" {{ $checked ? 'checked':''}} value="1" >
|
||||||
<div :class="toggle ? 'bg-blue-600' : 'bg-gray-200'" class="w-11 h-6 rounded-full transition-colors duration-300"></div>
|
<div :class="toggle ? 'bg-indigo-600' : 'bg-gray-200'" class="w-11 h-6 rounded-full transition-colors duration-300"></div>
|
||||||
<div :class="toggle ? 'translate-x-6' : 'translate-x-1'" class="absolute left-1 top-1 bg-white w-4 h-4 rounded-full transition-transform duration-300"></div>
|
<div :class="toggle ? 'translate-x-6' : 'translate-x-1'" class="absolute left-1 top-1 bg-white w-4 h-4 rounded-full transition-transform duration-300"></div>
|
||||||
</label>
|
</label>
|
||||||
@error($name)
|
@error($name)
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,16 @@
|
||||||
|
@php
|
||||||
|
/**
|
||||||
|
* @var string $method Method for the select form
|
||||||
|
* @var string $formRoute Route for the form action. Should be a route name
|
||||||
|
*/
|
||||||
|
@endphp
|
||||||
|
|
||||||
<x-layout.app>
|
<x-layout.app>
|
||||||
<x-slot:page_title>Choose Entry</x-slot:page_title>
|
<x-slot:page_title>Choose Entry</x-slot:page_title>
|
||||||
<x-card.card class="mx-auto max-w-sm">
|
<x-card.card class="mx-auto max-w-sm">
|
||||||
<x-card.heading>Choose Entry</x-card.heading>
|
<x-card.heading>Choose Entry</x-card.heading>
|
||||||
<div class="">
|
<div class="">
|
||||||
<x-form.form method="GET" action="{{ route('scores.entryScoreSheet') }}" class="mb-4 mt-3">
|
<x-form.form method="{{ $method }}" action="{{ route($formRoute) }}" class="mb-4 mt-3" id="entry-select-form">
|
||||||
<x-form.field name="entry_id" label_text="Entry ID"></x-form.field>
|
<x-form.field name="entry_id" label_text="Entry ID"></x-form.field>
|
||||||
<x-form.footer >
|
<x-form.footer >
|
||||||
<x-form.button>Select</x-form.button>
|
<x-form.button>Select</x-form.button>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
<x-layout.app x-data="{ showButton: {{ $scores ? 'false':'true' }} }">
|
||||||
|
@if($scores)
|
||||||
|
<x-card.card class="mx-auto max-w-2xl mb-3">
|
||||||
|
<x-card.heading class="text-red-600">
|
||||||
|
WARNING: Entry has existing scores
|
||||||
|
</x-card.heading>
|
||||||
|
<div class="grid md:grid-cols-3 px-4 space-x-3 pb-6">
|
||||||
|
@foreach($scores as $score)
|
||||||
|
<div>
|
||||||
|
<div class="my-3 border-b">{{ $score->judge->full_name() }}</div>
|
||||||
|
<ul>
|
||||||
|
@foreach($score->subscores as $subscore)
|
||||||
|
<div class="grid grid-cols-2 gap-x-8 border-b">
|
||||||
|
<span>{{ $subscore['subscore_name'] }}</span>
|
||||||
|
<span>{{ $subscore['score'] }}</span>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
<div class="pb-5 pl-5 flex gap-1">
|
||||||
|
<x-form.checkbox name="confirm" x-model="showButton" /> I understand that marking this entry as a no-show will delete existing scores. The scores cannot be recovered.
|
||||||
|
</div>
|
||||||
|
</x-card.card>
|
||||||
|
@endif
|
||||||
|
<x-card.card class="mx-auto max-w-md" x-show="showButton" x-cloak>
|
||||||
|
<x-card.heading>{{ $cardHeading }}</x-card.heading>
|
||||||
|
<x-card.list.body>
|
||||||
|
<x-card.list.row>
|
||||||
|
{{ $entry->student->full_name() }}
|
||||||
|
<x-card.list.row-text-subtext>{{$entry->school->name}}</x-card.list.row-text-subtext>
|
||||||
|
</x-card.list.row>
|
||||||
|
<x-card.list.row>
|
||||||
|
{{ $entry->audition->name }} #{{ $entry->draw_number ?? ' no draw number' }}
|
||||||
|
</x-card.list.row>
|
||||||
|
</x-card.list.body>
|
||||||
|
<x-form.footer class="mb-4">
|
||||||
|
<x-form.form method="{{ $method }}" action="{{route($submitRouteName, $entry)}}" id="{{ $formId }}">
|
||||||
|
<x-form.button type="submit" >{{ $buttonName }}</x-form.button>
|
||||||
|
</x-form.form>
|
||||||
|
</x-form.footer>
|
||||||
|
</x-card.card>
|
||||||
|
</x-layout.app>
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
<div class="flex items-center">
|
||||||
|
<label class="'relative inline-flex items-center cursor-pointer'">{{ $slot }}
|
||||||
|
<input type="checkbox" x-model="toggle" name="{{ $name }}" class="sr-only" {{ $checked ? 'checked':''}} value="1" >
|
||||||
|
<div :class="toggle ? 'bg-indigo-600' : 'bg-gray-200'" class="w-11 h-6 rounded-full transition-colors duration-300"></div>
|
||||||
|
<div :class="toggle ? 'translate-x-6' : 'translate-x-1'" class="absolute left-1 top-1 bg-white w-4 h-4 rounded-full transition-transform duration-300"></div>
|
||||||
|
</label>
|
||||||
|
|
@ -14,6 +14,14 @@ Route::middleware(['auth', 'verified', CheckIfCanTab::class])->group(function ()
|
||||||
Route::delete('/{score}', [\App\Http\Controllers\Tabulation\ScoreController::class, 'destroyScore'])->name('scores.destroy');
|
Route::delete('/{score}', [\App\Http\Controllers\Tabulation\ScoreController::class, 'destroyScore'])->name('scores.destroy');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Entry Flagging
|
||||||
|
Route::prefix('entry-flags/')->controller(\App\Http\Controllers\Tabulation\EntryFlagController::class)->group(function () {
|
||||||
|
Route::get('/choose_no_show', 'noShowSelect')->name('entry-flags.noShowSelect');
|
||||||
|
Route::get('/propose-no-show', 'noShowConfirm')->name('entry-flags.confirmNoShow');
|
||||||
|
Route::post('/no-show/{entry}', 'enterNoShow')->name('entry-flags.enterNoShow');
|
||||||
|
Route::delete('/no-show/{entry}', 'undoNoShow')->name('entry-flags.undoNoShow');
|
||||||
|
});
|
||||||
|
|
||||||
// Generic Tabulation Routes
|
// Generic Tabulation Routes
|
||||||
Route::prefix('tabulation/')->controller(\App\Http\Controllers\Tabulation\TabulationController::class)->group(function () {
|
Route::prefix('tabulation/')->controller(\App\Http\Controllers\Tabulation\TabulationController::class)->group(function () {
|
||||||
Route::get('/status', 'status')->name('tabulation.status');
|
Route::get('/status', 'status')->name('tabulation.status');
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,105 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Audition;
|
||||||
|
use App\Models\Entry;
|
||||||
|
use App\Models\Room;
|
||||||
|
use App\Models\ScoringGuide;
|
||||||
|
use App\Models\SubscoreDefinition;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Illuminate\Support\Facades\Artisan;
|
||||||
|
use Sinnbeck\DomAssertions\Asserts\AssertForm;
|
||||||
|
|
||||||
|
use function Pest\Laravel\get;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
it('only allows an admin or tab user to confirm a no-show', function () {
|
||||||
|
$entry = Entry::factory()->create();
|
||||||
|
get(route('entry-flags.confirmNoShow', ['entry_id' => $entry->id]))
|
||||||
|
->assertRedirect(route('home'));
|
||||||
|
actAsNormal();
|
||||||
|
get(route('entry-flags.confirmNoShow', ['entry_id' => $entry->id]))
|
||||||
|
->assertRedirect(route('dashboard'))
|
||||||
|
->assertSessionHas('error', 'You are not authorized to perform this action');
|
||||||
|
actAsTab();
|
||||||
|
get(route('entry-flags.confirmNoShow', ['entry_id' => $entry->id]))
|
||||||
|
->assertOk();
|
||||||
|
actAsAdmin();
|
||||||
|
get(route('entry-flags.confirmNoShow', ['entry_id' => $entry->id]))
|
||||||
|
->assertOk();
|
||||||
|
});
|
||||||
|
it('will not work with an entry if it is in a published audition', function () {
|
||||||
|
$entry1 = Entry::factory()->create();
|
||||||
|
$entry2 = Entry::factory()->create();
|
||||||
|
$entry1->audition->addFlag('seats_published');
|
||||||
|
$entry2->audition->addFlag('advance_published');
|
||||||
|
actAsTab();
|
||||||
|
get(route('entry-flags.confirmNoShow', ['entry_id' => $entry1->id]))
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'))
|
||||||
|
->assertSessionHas('error', 'Cannot enter a no-show for an entry in an audition where seats are published');
|
||||||
|
get(route('entry-flags.confirmNoShow', ['entry_id' => $entry2->id]))
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'))
|
||||||
|
->assertSessionHas('error', 'Cannot enter a no-show for an entry in an audition where advancement is published');
|
||||||
|
});
|
||||||
|
it('has information for the requested entry', function () {
|
||||||
|
// Arrange
|
||||||
|
$entry = Entry::factory()->create();
|
||||||
|
// Act & Assert
|
||||||
|
actAsTab();
|
||||||
|
get(route('entry-flags.confirmNoShow', ['entry_id' => $entry->id]))
|
||||||
|
->assertOk()
|
||||||
|
->assertSee($entry->student->full_name())
|
||||||
|
->assertSee($entry->audition->name)
|
||||||
|
->assertSee($entry->student->school->name)
|
||||||
|
->assertSee($entry->draw_number);
|
||||||
|
});
|
||||||
|
it('posts to entry-flags.enterNoShow and has a submit button', function () {
|
||||||
|
// Arrange
|
||||||
|
$entry = Entry::factory()->create();
|
||||||
|
// Act & Assert
|
||||||
|
actAsTab();
|
||||||
|
get(route('entry-flags.confirmNoShow', ['entry_id' => $entry->id]))
|
||||||
|
->assertOk()
|
||||||
|
->assertFormExists('#no-show-confirmation-form', function (AssertForm $form) use ($entry) {
|
||||||
|
$form->hasMethod('POST')
|
||||||
|
->hasAction(route('entry-flags.enterNoShow', ['entry' => $entry->id]))
|
||||||
|
->contains('button', ['type' => 'submit'])
|
||||||
|
->hasCSRF();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('posts to entry-flags.undoNoShow and has a remove button if the entry is already a noshow', function () {
|
||||||
|
// Arrange
|
||||||
|
$entry = Entry::factory()->create();
|
||||||
|
$entry->addFlag('no_show');
|
||||||
|
// Act & Assert
|
||||||
|
actAsTab();
|
||||||
|
get(route('entry-flags.confirmNoShow', ['entry_id' => $entry->id]))
|
||||||
|
->assertOk()
|
||||||
|
->assertFormExists('#no-show-cancellation-form', function (AssertForm $form) use ($entry) {
|
||||||
|
$form->hasMethod('POST')
|
||||||
|
->hasAction(route('entry-flags.undoNoShow', ['entry' => $entry->id]))
|
||||||
|
->contains('button', ['type' => 'submit'])
|
||||||
|
->hasCSRF();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('shows a box with scores if the entry is scored', function () {
|
||||||
|
// Arrange
|
||||||
|
$judges = User::factory()->count(3)->create();
|
||||||
|
$room = Room::factory()->create();
|
||||||
|
$judges->each(fn($judge) => $room->addJudge($judge->id));
|
||||||
|
$scoringGuide = ScoringGuide::factory()->create();
|
||||||
|
SubscoreDefinition::factory()->count(5)->create(['scoring_guide_id' => $scoringGuide->id]);
|
||||||
|
$audition = Audition::factory()->create(['room_id' => $room->id, 'scoring_guide_id' => $scoringGuide->id]);
|
||||||
|
$entry = Entry::factory()->create(['audition_id' => $audition->id]);
|
||||||
|
// Run the ScoreAllAuditions seeder
|
||||||
|
Artisan::call('db:seed', ['--class' => 'ScoreAllAuditions']);
|
||||||
|
// Act & Assert
|
||||||
|
actAsTab();
|
||||||
|
$response = get(route('entry-flags.confirmNoShow', ['entry_id' => $entry->id]));
|
||||||
|
$response->assertOk()
|
||||||
|
->assertSee('WARNING')
|
||||||
|
->assertSee('existing scores');
|
||||||
|
$judges->each(fn($judge) => $response->assertSee($judge->full_name()));
|
||||||
|
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,62 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Entry;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
use function Pest\Laravel\post;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
it('only allows an admin or tab user to enter a no-show', function () {
|
||||||
|
$entry = Entry::factory()->create();
|
||||||
|
post(route('entry-flags.enterNoShow', $entry))
|
||||||
|
->assertRedirect(route('home'));
|
||||||
|
actAsAdmin();
|
||||||
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
|
post(route('entry-flags.enterNoShow', $entry))
|
||||||
|
->assertSessionHasNoErrors()
|
||||||
|
->assertSessionHas('success',
|
||||||
|
'No Show has been entered for '.$entry->audition->name.' #'.$entry->draw_number.' (ID: '.$entry->id.').')
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'));
|
||||||
|
actAsTab();
|
||||||
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
|
post(route('entry-flags.enterNoShow', $entry))
|
||||||
|
->assertSessionHasNoErrors()
|
||||||
|
->assertSessionHas('success',
|
||||||
|
'No Show has been entered for '.$entry->audition->name.' #'.$entry->draw_number.' (ID: '.$entry->id.').')
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'));
|
||||||
|
});
|
||||||
|
it('will not record an entry in a published audition as a no show', function () {
|
||||||
|
$entry1 = Entry::factory()->create();
|
||||||
|
$entry2 = Entry::factory()->create();
|
||||||
|
$entry1->audition->addFlag('seats_published');
|
||||||
|
$entry2->audition->addFlag('advance_published');
|
||||||
|
actAsAdmin();
|
||||||
|
post(route('entry-flags.enterNoShow', $entry1))
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'))
|
||||||
|
->assertSessionHas('error', 'Cannot enter a no-show for an entry in an audition where seats are published');
|
||||||
|
post(route('entry-flags.enterNoShow', $entry2))
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'))
|
||||||
|
->assertSessionHas('error',
|
||||||
|
'Cannot enter a no-show for an entry in an audition where advancement is published');
|
||||||
|
});
|
||||||
|
it('deletes all scores for an entry when a no-show is entered', function () {
|
||||||
|
$entry = Entry::factory()->create();
|
||||||
|
$judges = User::factory()->count(3)->create();
|
||||||
|
$entry->scoreSheets()->create(['user_id' => $judges[0]->id, 'subscores' => 10]);
|
||||||
|
$entry->scoreSheets()->create(['user_id' => $judges[1]->id, 'subscores' => 10]);
|
||||||
|
$entry->scoreSheets()->create(['user_id' => $judges[2]->id, 'subscores' => 10]);
|
||||||
|
expect($entry->scoreSheets()->count())->toBe(3);
|
||||||
|
actAsAdmin();
|
||||||
|
post(route('entry-flags.enterNoShow', $entry));
|
||||||
|
expect($entry->scoreSheets()->count())->toBe(0);
|
||||||
|
});
|
||||||
|
it('adds a no_show flag to the entry', function () {
|
||||||
|
// Arrange
|
||||||
|
$entry = Entry::factory()->create();
|
||||||
|
// Act & Assert
|
||||||
|
actAsAdmin();
|
||||||
|
post(route('entry-flags.enterNoShow', $entry));
|
||||||
|
expect(Entry::find($entry->id)->hasFlag('no_show'))->toBeTrue();
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
use Sinnbeck\DomAssertions\Asserts\AssertElement;
|
||||||
|
use Sinnbeck\DomAssertions\Asserts\AssertForm;
|
||||||
|
|
||||||
|
use function Pest\Laravel\get;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
it('responds to only admin and tab users', function () {
|
||||||
|
get(route('entry-flags.noShowSelect'))
|
||||||
|
->assertRedirect(route('home'));
|
||||||
|
actAsAdmin();
|
||||||
|
get(route('entry-flags.noShowSelect'))
|
||||||
|
->assertOk();
|
||||||
|
actAsTab();
|
||||||
|
get(route('entry-flags.noShowSelect'))
|
||||||
|
->assertOk();
|
||||||
|
actAsNormal();
|
||||||
|
get(route('entry-flags.noShowSelect'))
|
||||||
|
->assertRedirect(route('dashboard'))
|
||||||
|
->assertSessionHas('error', 'You are not authorized to perform this action');
|
||||||
|
});
|
||||||
|
it('has an input for entry_id', function () {
|
||||||
|
actAsAdmin();
|
||||||
|
get(route('entry-flags.noShowSelect'))
|
||||||
|
->assertOk()
|
||||||
|
->assertElementExists('#entry_id', function (AssertElement $element) {
|
||||||
|
$element->is('input');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
it('submits to entry-flags.confirmNoShow', function () {
|
||||||
|
actAsAdmin();
|
||||||
|
get(route('entry-flags.noShowSelect'))
|
||||||
|
->assertOk()
|
||||||
|
->assertFormExists('#entry-select-form', function (AssertForm $form) {
|
||||||
|
$form->hasMethod('GET')
|
||||||
|
->hasAction(route('entry-flags.confirmNoShow'));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use App\Models\Entry;
|
||||||
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||||
|
|
||||||
|
use function Pest\Laravel\delete;
|
||||||
|
|
||||||
|
uses(RefreshDatabase::class);
|
||||||
|
|
||||||
|
it('only allows an admin or tab user to undo a no-show', function () {
|
||||||
|
$entry = Entry::factory()->create();
|
||||||
|
$entry->addFlag('no_show');
|
||||||
|
delete(route('entry-flags.undoNoShow', $entry))
|
||||||
|
->assertRedirect(route('home'));
|
||||||
|
actAsAdmin();
|
||||||
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
|
delete(route('entry-flags.undoNoShow', $entry))
|
||||||
|
->assertSessionHasNoErrors()
|
||||||
|
->assertSessionHas('success',
|
||||||
|
'No Show status has been removed for '.$entry->audition->name.' #'.$entry->draw_number.' (ID: '.$entry->id.').')
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'));
|
||||||
|
actAsTab();
|
||||||
|
/** @noinspection PhpUnhandledExceptionInspection */
|
||||||
|
delete(route('entry-flags.undoNoShow', $entry))
|
||||||
|
->assertSessionHasNoErrors()
|
||||||
|
->assertSessionHas('success',
|
||||||
|
'No Show status has been removed for '.$entry->audition->name.' #'.$entry->draw_number.' (ID: '.$entry->id.').')
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'));
|
||||||
|
});
|
||||||
|
it('will not undo a no-show flag for an entry in a published audition', function () {
|
||||||
|
$entry1 = Entry::factory()->create();
|
||||||
|
$entry2 = Entry::factory()->create();
|
||||||
|
$entry1->addFlag('no_show');
|
||||||
|
$entry2->addFlag('no_show');
|
||||||
|
$entry1->audition->addFlag('seats_published');
|
||||||
|
$entry2->audition->addFlag('advance_published');
|
||||||
|
actAsAdmin();
|
||||||
|
delete(route('entry-flags.undoNoShow', $entry1))
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'))
|
||||||
|
->assertSessionHas('error', 'Cannot undo a no-show for an entry in an audition where seats are published');
|
||||||
|
delete(route('entry-flags.undoNoShow', $entry2))
|
||||||
|
->assertRedirect(route('entry-flags.noShowSelect'))
|
||||||
|
->assertSessionHas('error',
|
||||||
|
'Cannot undo a no-show for an entry in an audition where advancement is published');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('removes a no_show flag to the entry', function () {
|
||||||
|
// Arrange
|
||||||
|
$entry = Entry::factory()->create();
|
||||||
|
$entry->addFlag('no_show');
|
||||||
|
// Act & Assert
|
||||||
|
actAsAdmin();
|
||||||
|
delete(route('entry-flags.undoNoShow', $entry));
|
||||||
|
expect(Entry::find($entry->id)->hasFlag('no_show'))->toBeFalse();
|
||||||
|
});
|
||||||
Loading…
Reference in New Issue