Testing for DoublerRequestController.php
This commit is contained in:
parent
ba55d75172
commit
96b590365a
|
|
@ -2,88 +2,62 @@
|
|||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\AuditLogEntry;
|
||||
use App\Http\Requests\DoublerRequestsStoreRequest;
|
||||
use App\Models\DoublerRequest;
|
||||
use App\Models\Event;
|
||||
use App\Models\Student;
|
||||
use App\Services\DoublerService;
|
||||
use Barryvdh\Debugbar\Facades\Debugbar;
|
||||
use Psr\Container\ContainerExceptionInterface;
|
||||
use Psr\Container\NotFoundExceptionInterface;
|
||||
use Illuminate\Contracts\Foundation\Application;
|
||||
use Illuminate\Contracts\View\Factory;
|
||||
use Illuminate\Contracts\View\View;
|
||||
|
||||
use function auth;
|
||||
use function compact;
|
||||
use function request;
|
||||
use function to_route;
|
||||
|
||||
class DoublerRequestController extends Controller
|
||||
{
|
||||
public function index(DoublerService $doublerService)
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* Data sent to view:
|
||||
* - events - all existing events
|
||||
* - existingRequests - previously made requests for each event, keyed by student id
|
||||
* existingRequest[eventId][student id]-> Request
|
||||
* - doublers - existing doublers, grouped by event. Keyed by event_id and student_id
|
||||
*
|
||||
* @return Application|Factory|View|\Illuminate\Foundation\Application|\Illuminate\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$events = Event::all();
|
||||
$students = auth()->user()->school->students;
|
||||
$studentIds = $students->pluck('id');
|
||||
$existingRequests = DoublerRequest::whereIn('student_id', $studentIds)->get();
|
||||
$doublers = [];
|
||||
foreach ($events as $event) {
|
||||
$event_doublers = $doublerService->doublersForEvent($event);
|
||||
$doublers[$event->id] = $event_doublers;
|
||||
$existingRequests = auth()->user()->school->doublerRequests
|
||||
->groupBy('event_id')
|
||||
->map(function ($requestsForEvent) {
|
||||
return $requestsForEvent->keyBy('student_id');
|
||||
});
|
||||
$doublers = auth()->user()->school->doublers()
|
||||
->with('student')
|
||||
->with('event')
|
||||
->get()
|
||||
->groupBy('event_id');
|
||||
|
||||
return view('doubler_request.index', compact('events', 'doublers', 'existingRequests'));
|
||||
}
|
||||
|
||||
return view('doubler_request.index', compact('events', 'doublers', 'students', 'existingRequests'));
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws ContainerExceptionInterface
|
||||
* @throws NotFoundExceptionInterface
|
||||
*/
|
||||
public function makeRequest()
|
||||
public function makeRequest(DoublerRequestsStoreRequest $request)
|
||||
{
|
||||
foreach (request()->get('doubler_requests') as $event_id => $requests) {
|
||||
if (! Event::find($event_id)->exists()) {
|
||||
return to_route('doubler_request.index')->with('error', 'Invalid event id specified');
|
||||
}
|
||||
$thisEvent = Event::find($event_id);
|
||||
foreach ($requests as $student_id => $request) {
|
||||
if (! Student::find($student_id)->exists()) {
|
||||
return to_route('doubler_request.index')->with('error', 'Invalid student id specified');
|
||||
}
|
||||
$thisStudent = Student::find($student_id);
|
||||
if (! $request) {
|
||||
$oldRequest = DoublerRequest::where('student_id', $student_id)
|
||||
->where('event_id', $event_id)
|
||||
->first();
|
||||
if ($oldRequest) {
|
||||
Debugbar::info('hit');
|
||||
AuditLogEntry::create([
|
||||
'user' => auth()->user()->email,
|
||||
'ip_address' => request()->ip(),
|
||||
'message' => 'Removed doubler request for '.$thisStudent->full_name().' in '.$thisEvent->name,
|
||||
'affected' => ['students' => [$student_id]],
|
||||
]);
|
||||
$oldRequest->delete();
|
||||
}
|
||||
foreach ($request->getDoublerRequests() as $thisRequest) {
|
||||
|
||||
continue;
|
||||
}
|
||||
DoublerRequest::upsert([
|
||||
'event_id' => $event_id,
|
||||
'student_id' => $student_id,
|
||||
'request' => $request,
|
||||
'event_id' => $thisRequest['event_id'],
|
||||
'student_id' => $thisRequest['student_id'],
|
||||
'request' => $thisRequest['request'],
|
||||
],
|
||||
uniqueBy: ['event_id', 'student_id'],
|
||||
update: ['request']
|
||||
);
|
||||
AuditLogEntry::create([
|
||||
'user' => auth()->user()->email,
|
||||
'ip_address' => request()->ip(),
|
||||
'message' => 'Made doubler request for '.$thisStudent->full_name().' in '.$thisEvent->name.'<br>Request: '.$request,
|
||||
'affected' => ['students' => [$student_id]],
|
||||
]);
|
||||
}
|
||||
}
|
||||
echo 'hi';
|
||||
|
||||
return to_route('doubler_request.index')->with('success', 'Recorded doubler requests');
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,76 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
|
||||
class DoublerRequestsStoreRequest extends FormRequest
|
||||
{
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'doubler_requests' => ['required', 'array'],
|
||||
|
||||
// Validate event IDs (first keys)
|
||||
'doubler_requests.*' => ['required', 'array'],
|
||||
|
||||
// Validate student IDs (second keys) and their values
|
||||
'doubler_requests.*.*' => [
|
||||
'required',
|
||||
'string',
|
||||
'max:50',
|
||||
// Custom validation rule to check if the student ID exists in DB
|
||||
function ($attribute, $value, $fail) {
|
||||
// $attribute will be like "doubler_requests.1.107"
|
||||
// Extract event_id and student_id from attribute
|
||||
preg_match('/doubler_requests\.(\d+)\.(\d+)/', $attribute, $matches);
|
||||
if (! $matches) {
|
||||
$fail('Invalid attribute format.');
|
||||
|
||||
return;
|
||||
}
|
||||
$eventId = $matches[1];
|
||||
$studentId = $matches[2];
|
||||
|
||||
// Check event ID exists
|
||||
if (! \App\Models\Event::where('id', $eventId)->exists()) {
|
||||
$fail("Event ID {$eventId} does not exist.");
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Check student ID exists
|
||||
if (! \App\Models\Student::where('id', $studentId)->exists()) {
|
||||
$fail("Student ID {$studentId} does not exist.");
|
||||
|
||||
return;
|
||||
}
|
||||
},
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
public function getDoublerRequests(): array
|
||||
{
|
||||
$validated = $this->validated()['doubler_requests'] ?? [];
|
||||
|
||||
$result = [];
|
||||
|
||||
foreach ($validated as $eventId => $students) {
|
||||
foreach ($students as $studentId => $request) {
|
||||
$result[] = [
|
||||
'event_id' => (int) $eventId,
|
||||
'student_id' => (int) $studentId,
|
||||
'request' => $request,
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
public function authorize(): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ class Doubler extends Model
|
|||
|
||||
public function entries()
|
||||
{
|
||||
return Entry::whereIn('id', $this->entries)->get();
|
||||
return Entry::whereIn('id', $this->entries)->with('student')->with('audition')->get();
|
||||
}
|
||||
|
||||
// Find a doubler based on both keys
|
||||
|
|
|
|||
|
|
@ -10,15 +10,21 @@ use App\Actions\Tabulation\TotalEntryScores;
|
|||
use App\Models\BonusScore;
|
||||
use App\Models\Entry;
|
||||
use App\Models\EntryFlag;
|
||||
use App\Models\Event;
|
||||
use App\Models\School;
|
||||
use App\Models\SchoolEmailDomain;
|
||||
use App\Models\ScoreSheet;
|
||||
use App\Models\Student;
|
||||
use App\Models\User;
|
||||
use App\Observers\BonusScoreObserver;
|
||||
use App\Observers\EntryFlagObserver;
|
||||
use App\Observers\EntryObserver;
|
||||
use App\Observers\EventObserver;
|
||||
use App\Observers\SchoolEmailDomainObserver;
|
||||
use App\Observers\SchoolObserver;
|
||||
use App\Observers\ScoreSheetObserver;
|
||||
use App\Observers\StudentObserver;
|
||||
use App\Observers\UserObserver;
|
||||
use App\Services\AuditionService;
|
||||
use App\Services\DoublerService;
|
||||
use App\Services\DrawService;
|
||||
|
|
@ -55,10 +61,13 @@ class AppServiceProvider extends ServiceProvider
|
|||
{
|
||||
BonusScore::observe(BonusScoreObserver::class);
|
||||
Entry::observe(EntryObserver::class);
|
||||
EntryFlag::observe(EntryFlagObserver::class);
|
||||
Event::observe(EventObserver::class);
|
||||
School::observe(SchoolObserver::class);
|
||||
SchoolEmailDomain::observe(SchoolEmailDomainObserver::class);
|
||||
ScoreSheet::observe(ScoreSheetObserver::class);
|
||||
Student::observe(StudentObserver::class);
|
||||
EntryFlag::observe(EntryFlagObserver::class);
|
||||
User::observe(UserObserver::class);
|
||||
|
||||
// Model::preventLazyLoading(! app()->isProduction());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,24 +13,18 @@
|
|||
</tr>
|
||||
</thead>
|
||||
<x-table.body>
|
||||
@foreach($students as $student)
|
||||
@continue(! array_key_exists($student->id, $doublers[$event->id]))
|
||||
@php
|
||||
$existingRequest = $existingRequests
|
||||
->where('student_id',$student->id)
|
||||
->where('event_id',$event->id);
|
||||
$value = $existingRequest?->first()?->request ?? '';
|
||||
@endphp
|
||||
@foreach($doublers[$event->id] ?? [] as $doubler)
|
||||
@php($student = $doubler->student)
|
||||
<tr>
|
||||
<x-table.td>{{ $student->full_name() }}</x-table.td>
|
||||
<x-table.td>
|
||||
@foreach($doublers[$event->id][$student->id]['entries'] as $entry)
|
||||
<p>{{$entry->audition->name}}</p>
|
||||
@foreach($doubler->entries() as $entry)
|
||||
<p>{{ $entry->audition->name }}</p>
|
||||
@endforeach
|
||||
</x-table.td>
|
||||
<x-table.td>
|
||||
<x-form.field
|
||||
value="{{$value}}"
|
||||
value="{{ $existingRequests[$event->id][$student->id] ?? '' }}"
|
||||
name="doubler_requests[{{$event->id}}][{{$student->id}}]"/>
|
||||
</x-table.td>
|
||||
</tr>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,92 @@
|
|||
<?php
|
||||
|
||||
/** @noinspection PhpUnhandledExceptionInspection */
|
||||
|
||||
use App\Actions\Entries\CreateEntry;
|
||||
use App\Models\Audition;
|
||||
use App\Models\AuditLogEntry;
|
||||
use App\Models\DoublerRequest;
|
||||
use App\Models\Event;
|
||||
use App\Models\School;
|
||||
use App\Models\Student;
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Testing\RefreshDatabase;
|
||||
|
||||
use function Pest\Laravel\actingAs;
|
||||
|
||||
uses(RefreshDatabase::class);
|
||||
|
||||
describe('index', function () {
|
||||
it('returns a form to enter doubler requests', function () {
|
||||
$school = School::factory()->create();
|
||||
$user = User::factory()->forSchool($school)->create();
|
||||
actingAs($user);
|
||||
$event = Event::factory()->create(['name' => 'Concert']);
|
||||
$event2 = Event::factory()->create(['name' => 'Jazz']);
|
||||
$audition11 = Audition::factory()->create([
|
||||
'minimum_grade' => 1, 'maximum_grade' => 15, 'event_id' => $event->id,
|
||||
]);
|
||||
$audition12 = Audition::factory()->create([
|
||||
'minimum_grade' => 1, 'maximum_grade' => 15, 'event_id' => $event->id,
|
||||
]);
|
||||
$audition21 = Audition::factory()->create([
|
||||
'minimum_grade' => 1, 'maximum_grade' => 15, 'event_id' => $event2->id,
|
||||
]);
|
||||
$audition22 = Audition::factory()->create([
|
||||
'minimum_grade' => 1, 'maximum_grade' => 15, 'event_id' => $event2->id,
|
||||
]);
|
||||
$student = Student::factory()->forSchool($school)->create();
|
||||
$entryDesk = app(CreateEntry::class);
|
||||
$entryDesk($student, $audition11);
|
||||
$entryDesk($student, $audition12);
|
||||
$entryDesk($student, $audition21);
|
||||
$entryDesk($student, $audition22);
|
||||
DoublerRequest::create([
|
||||
'event_id' => $event2->id,
|
||||
'student_id' => $student->id,
|
||||
'request' => 'request body',
|
||||
]);
|
||||
|
||||
$response = $this->get(route('doubler_request.index'));
|
||||
$response->assertOk();
|
||||
$viewEvents = $response->viewData('events');
|
||||
$viewDoublers = $response->viewData('doublers');
|
||||
$viewExistingRequests = $response->viewData('existingRequests');
|
||||
expect($viewEvents)->toHaveCount(2)
|
||||
->and($viewDoublers)->toHaveCount(2)
|
||||
->and($viewDoublers[$event->id]->count())->toBe(1)
|
||||
->and($viewExistingRequests[$event2->id][$student->id]->request)->toBe('request body');
|
||||
});
|
||||
});
|
||||
|
||||
describe('makeRequest', function () {
|
||||
it('submits a request', function () {
|
||||
$school = School::factory()->create();
|
||||
$user = User::factory()->forSchool($school)->create();
|
||||
$event1 = Event::factory()->create();
|
||||
$event2 = Event::factory()->create();
|
||||
$student = Student::factory()->forSchool($school)->create();
|
||||
$student2 = Student::factory()->forSchool($school)->create();
|
||||
actingAs($user);
|
||||
$response = $this->post(route('doubler_request.make_request'), [
|
||||
'doubler_requests' => [
|
||||
$event1->id => [
|
||||
$student->id => 'student 1 request in event 1',
|
||||
$student2->id => 'student 2 request in event 1',
|
||||
],
|
||||
$event2->id => [
|
||||
$student->id => 'student 1 request in event 2',
|
||||
$student2->id => 'student 2 request in event 2',
|
||||
],
|
||||
],
|
||||
]);
|
||||
$response->assertRedirect(route('doubler_request.index'));
|
||||
expect(DoublerRequest::count())->toBe(4)
|
||||
->and(DoublerRequest::where('event_id', $event2->id)->where('student_id',
|
||||
$student->id)->first()->request)->toBe('student 1 request in event 2');
|
||||
|
||||
foreach (AuditLogEntry::all() as $logEntry) {
|
||||
dump($logEntry->message);
|
||||
}
|
||||
});
|
||||
});
|
||||
Loading…
Reference in New Issue