diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php index 22ab1971..bc0efb02 100644 --- a/app/Http/Controllers/DashboardController.php +++ b/app/Http/Controllers/DashboardController.php @@ -19,7 +19,7 @@ class DashboardController extends Controller public function index(): Response { // get events ordered by sort_order - $events = Event::orderBy('sort_order')->get(); + $events = Event::orderBy('sort_order')->with('courses')->get(); // get registrations of the user $registrations = Auth::user()->registrations; diff --git a/app/Http/Controllers/DashboardEventController.php b/app/Http/Controllers/DashboardEventController.php index 47abe9de..1867f59d 100644 --- a/app/Http/Controllers/DashboardEventController.php +++ b/app/Http/Controllers/DashboardEventController.php @@ -6,6 +6,7 @@ use App\Models\Registration; use Illuminate\Http\RedirectResponse; use Illuminate\Http\Request; +use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Redirect; use Illuminate\Support\Facades\Session; use Inertia\Inertia; @@ -41,7 +42,7 @@ protected function redirectToEvent(Event $event): RedirectResponse * Redirect to the event page for the given event if the registration is not possible * * - * @return \Illuminate\Http\RedirectResponse|void + * @return RedirectResponse|void */ protected function redirectToEventIfNoRegistrationIsPossible(Event $event) { @@ -58,13 +59,22 @@ protected function redirectToEventIfNoRegistrationIsPossible(Event $event) return $this->redirectToEvent($event); } + + // check if the user has the right courses to register + if ($event->courses()->exists()) { + if (! $event->courses()->where('course_id', Auth::user()->course_id)->exists()) { + Session::flash('error', 'Du kannst dich mit deinem Studiengang zu diesem Event nicht anmelden.'); + + return $this->redirectToEvent($event); + } + } } /** * Redirect to the event page for the given event if the unregistration is not possible * * - * @return \Illuminate\Http\RedirectResponse|void + * @return RedirectResponse|void */ protected function redirectToEventIfNoUnregistrationIsPossible(Event $event) { @@ -111,14 +121,14 @@ public function index(Request $request): Response /** * Display the event register page */ - public function register(Request $request): Response + public function register(Request $request): Response|RedirectResponse { $event = $this->getEvent($request); if ($event instanceof \Inertia\Response) { return $event; } $registrationIsPossible = $this->redirectToEventIfNoRegistrationIsPossible($event); - if ($registrationIsPossible instanceof \Illuminate\Http\RedirectResponse) { + if ($registrationIsPossible instanceof RedirectResponse) { return $registrationIsPossible; } $event->slots = $event->slots()->get(); @@ -131,14 +141,14 @@ public function register(Request $request): Response /** * Display the event unregister page */ - public function unregister(Request $request): Response + public function unregister(Request $request): Response|RedirectResponse { $event = $this->getEvent($request); if ($event instanceof \Inertia\Response) { return $event; } $unregistrationIsPossible = $this->redirectToEventIfNoUnregistrationIsPossible($event); - if ($unregistrationIsPossible instanceof \Illuminate\Http\RedirectResponse) { + if ($unregistrationIsPossible instanceof RedirectResponse) { return $unregistrationIsPossible; } @@ -157,7 +167,7 @@ public function registerUser(Request $request): RedirectResponse return $event; } $registrationIsPossible = $this->redirectToEventIfNoRegistrationIsPossible($event); - if ($registrationIsPossible instanceof \Illuminate\Http\RedirectResponse) { + if ($registrationIsPossible instanceof RedirectResponse) { return $registrationIsPossible; } @@ -245,7 +255,7 @@ public function unregisterUser(Request $request): RedirectResponse return $event; } $unregistrationIsPossible = $this->redirectToEventIfNoUnregistrationIsPossible($event); - if ($unregistrationIsPossible instanceof \Illuminate\Http\RedirectResponse) { + if ($unregistrationIsPossible instanceof RedirectResponse) { return $unregistrationIsPossible; } diff --git a/app/Http/Controllers/DashboardTutorController.php b/app/Http/Controllers/DashboardTutorController.php index 68182fa0..c2a97ca5 100644 --- a/app/Http/Controllers/DashboardTutorController.php +++ b/app/Http/Controllers/DashboardTutorController.php @@ -18,7 +18,7 @@ class DashboardTutorController extends Controller public function index(): Response { // get events ordered by sort_order - $events = Event::orderBy('sort_order')->with('registrations')->get(); + $events = Event::orderBy('sort_order')->with('registrations')->with('courses')->get(); return Inertia::render('Dashboard/Tutor/Index', [ 'events' => $events, diff --git a/app/Models/CourseEvent.php b/app/Models/CourseEvent.php new file mode 100644 index 00000000..65e2db07 --- /dev/null +++ b/app/Models/CourseEvent.php @@ -0,0 +1,37 @@ +belongsTo(Course::class); + } + + /** + * Get event for the course_event. + */ + public function event(): BelongsTo + { + return $this->belongsTo(Event::class); + } +} diff --git a/app/Models/Event.php b/app/Models/Event.php index 0fdadfdf..07583891 100644 --- a/app/Models/Event.php +++ b/app/Models/Event.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\Relations\BelongsToMany; use Illuminate\Database\Eloquent\Relations\HasMany; use OwenIt\Auditing\Contracts\Auditable; @@ -63,4 +64,12 @@ public function stations(): HasMany { return $this->hasMany(Station::class); } + + /** + * Get courses for the group. + */ + public function courses(): BelongsToMany + { + return $this->belongsToMany(Course::class, 'course_event')->using(CourseEvent::class); + } } diff --git a/database/migrations/2024_09_15_084701_create_course_event_table.php b/database/migrations/2024_09_15_084701_create_course_event_table.php new file mode 100644 index 00000000..b40b7d31 --- /dev/null +++ b/database/migrations/2024_09_15_084701_create_course_event_table.php @@ -0,0 +1,29 @@ +id(); + $table->timestamps(); + $table->foreignId('course_id')->constrained()->onUpdate('cascade')->onDelete('cascade'); + $table->foreignId('event_id')->constrained()->onUpdate('cascade')->onDelete('cascade'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('course_event'); + } +}; diff --git a/database/seeders/EventsDemoSeeder.php b/database/seeders/EventsDemoSeeder.php index 2c0acdc0..69e7602a 100644 --- a/database/seeders/EventsDemoSeeder.php +++ b/database/seeders/EventsDemoSeeder.php @@ -3,6 +3,7 @@ namespace Database\Seeders; use App\Models\Course; +use App\Models\CourseEvent; use App\Models\CourseGroup; use App\Models\Event; use App\Models\Group; @@ -20,6 +21,7 @@ class EventsDemoSeeder extends Seeder public function run(): void { $this->runGroupPhase(); + $this->runGroupPhaseLimitedCourses(); $this->runGroupPhaseByCourse(); $this->runEventRegistration(); $this->runSlotBooking(); @@ -86,6 +88,93 @@ public function runGroupPhase(): void } } + /** + * Run the "groupPhaseLimitedCourses" event seeds. + */ + public function runGroupPhaseLimitedCourses(): void + { + // check if event with name "group_phase-limited_courses" exists + $event = Event::where('name', 'group_phase-limited_courses')->first(); + if ($event) { + return; + } + + // set registration_from and registration_to + $registration_from = new DateTime(NOW()); + $registration_to = new DateTime(NOW()); + $registration_to->modify('+7 days'); + + // create a new event + $event = new Event; + $event->name = 'group_phase-limited_courses'; + $event->description = 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed vitae eros vitae nisl ultrices ult.'; + $event->type = 'group_phase'; + $event->registration_from = $registration_from; + $event->registration_to = $registration_to; + $event->has_requirements = false; + $event->consider_alcohol = true; + $event->sort_order = 110; + + // save the event + $event->save(); + + // create event groups + $groups = []; + for ($i = 1; $i <= 14; $i++) { + $groups[] = [ + 'name' => "Gruppe $i", + 'telegram_group_link' => "https://example.com/invalid-telegram-link", + ]; + } + + // save groups + foreach ($groups as $groupData) { + $group = new Group; + $group->name = $groupData['name']; + $group->event_id = $event->id; + $group->telegram_group_link = $groupData['telegram_group_link']; + $group->save(); + } + + // get all courses + $courses = Course::all(); + + // map courses by abbreviation + $coursesByAbbreviation = []; + foreach ($courses as $course) { + $coursesByAbbreviation[$course->abbreviation] = $course; + } + + // allowed courses + $allowedCourses = [ + 'ISE-Master', + 'IS-Master', + 'INF-Master', + 'ET-Master', + ]; + + // save courses + foreach ($allowedCourses as $courseAbbreviation) { + $course = $coursesByAbbreviation[$courseAbbreviation]; + $course_event = new CourseEvent; + $course_event->course_id = $course->id; + $course_event->event_id = $event->id; + $course_event->save(); + } + + // get all users without roles + $users = User::doesntHave('roles')->get(); + + // register users to event + foreach ($users as $user) { + // create registration + $event->registrations()->create([ + 'user_id' => $user->id, + 'drinks_alcohol' => rand(0, 1) == 1, + ]); + } + } + /** * Run the "groupPhaseByCourse" event seeds. */ @@ -168,7 +257,7 @@ public function runGroupPhaseByCourse(): void $group->event_id = $event->id; $group->save(); - foreach ( $coursesCollection[$groupData['collection']] as $course){ + foreach ($coursesCollection[$groupData['collection']] as $course) { $coursegroup = new CourseGroup; $coursegroup->course_id = $coursesByAbbreviation[$course]->id; $coursegroup->group_id = $group->id; diff --git a/database/seeders/EventsErstiwocheSeeder.php b/database/seeders/EventsErstiwocheSeeder.php index 90897e93..e601147d 100644 --- a/database/seeders/EventsErstiwocheSeeder.php +++ b/database/seeders/EventsErstiwocheSeeder.php @@ -3,6 +3,7 @@ namespace Database\Seeders; use App\Models\Course; +use App\Models\CourseEvent; use App\Models\CourseGroup; use App\Models\Event; use App\Models\Group; @@ -18,6 +19,7 @@ class EventsErstiwocheSeeder extends Seeder public function run(): void { $this->runGruppenphase(); + $this->runGruppenphaseISMaster(); $this->runStadtrallye(); $this->runHausfuehrung(); $this->runKneipentour(); @@ -80,6 +82,99 @@ public function runGruppenphase(): void $group->event_id = $event->id; $group->save(); } + + // get all courses + $courses = Course::all(); + + // map courses by abbreviation + $coursesByAbbreviation = []; + foreach ($courses as $course) { + $coursesByAbbreviation[$course->abbreviation] = $course; + } + + // allowed courses + $allowedCourses = [ + 'INF', + 'ET', + 'DIB', + 'MCD', + 'WI', + 'SBE', + 'ISE-Master', + 'ET-Master', + 'INF-Master', + // only 'IS-Master' is excluded here + ]; + + // save courses + foreach ($allowedCourses as $courseAbbreviation) { + $course = $coursesByAbbreviation[$courseAbbreviation]; + $course_event = new CourseEvent; + $course_event->course_id = $course->id; + $course_event->event_id = $event->id; + $course_event->save(); + } + } + + /** + * Run the "Gruppenphase" event seeds. + */ + public function runGruppenphaseISMaster(): void + { + // check if event with name "Gruppenphase" exists + $event = Event::where('name', 'Gruppenphase')->where('description', 'like', '%' . 'M.Sc. Information Systems' . '%')->first(); + if ($event) { + return; + } + + // create a new event + $event = new Event; + $event->name = 'Gruppenphase'; + $event->description = '

Während der Gruppenphase erhältst du von deinen Tutoren und Tutorinnen wichtige Informationen rund um das Studium. Außerdem ist die Gruppenphase dazu da, um direkt die anderen Erstis kennenzulernen und erste Freundschaften zu schließen.

+

Diese Gruppenphase ist speziell für Studierende des Studiengangs M.Sc. Information Systems, da dort einige Besonderheiten erklärt werden.

'; + $event->type = 'group_phase'; + $event->registration_from = new DateTime('2023-09-25 8:00:00'); + $event->registration_to = new DateTime('2023-09-25 12:30:00'); + $event->has_requirements = false; + $event->consider_alcohol = false; + $event->sort_order = 101; + + // save the event + $event->save(); + + // create event groups + $groupNames = [ + 'Die masterhaften Mammuts', + ]; + foreach ($groupNames as $groupName) { + $group = new Group; + $group->name = $groupName; + $group->event_id = $event->id; + $group->save(); + } + + // get all courses + $courses = Course::all(); + + // map courses by abbreviation + $coursesByAbbreviation = []; + foreach ($courses as $course) { + $coursesByAbbreviation[$course->abbreviation] = $course; + } + + // allowed courses + $allowedCourses = [ + 'IS-Master', + ]; + + // save courses + foreach ($allowedCourses as $courseAbbreviation) { + $course = $coursesByAbbreviation[$courseAbbreviation]; + $course_event = new CourseEvent; + $course_event->course_id = $course->id; + $course_event->event_id = $event->id; + $course_event->save(); + } } /** @@ -261,7 +356,7 @@ public function runHausfuehrung(): void $group->save(); // save course_group collections - foreach ($group->course_ids as $course_id) { + foreach ($groupData['course_ids'] as $course_id) { $course_group = new CourseGroup; $course_group->course_id = $course_id; $course_group->group_id = $group->id; diff --git a/resources/js/components/event/Table.vue b/resources/js/components/event/Table.vue index 7f0c4830..97f0ab1c 100644 --- a/resources/js/components/event/Table.vue +++ b/resources/js/components/event/Table.vue @@ -19,6 +19,17 @@ > Type + + Studiengänge + + {{ + event.courses.length == 0 + ? "Alle" + : event.courses + .map((course) => course.abbreviation) + .join(", ") + }} + ['admin'].includes(role))" + type="password" + name="password" + label="Adminpasswort" + placeholder="Passwort" + validation="required" + /> + @@ -88,4 +99,16 @@ const getUserRegistrationForEvent = (event: App.Models.Event) => { (registration) => registration.event_id === event.id, ); }; + +const isUserAllowedToRegister = ( + event: App.Models.Event, + user: Models.User, +) => { + return ( + event.courses.length === 0 || + event.courses.some((course) => { + return user.course_id === course.id; + }) + ); +}; diff --git a/resources/js/types/course-event.d.ts b/resources/js/types/course-event.d.ts new file mode 100644 index 00000000..566f4e29 --- /dev/null +++ b/resources/js/types/course-event.d.ts @@ -0,0 +1,11 @@ +declare namespace App.Models { + type CourseEvent = { + id: number; + created_at: string /* Date */ | null; + updated_at: string /* Date */ | null; + course_id: number; + event_id: number; + course?: Course | null; + event?: Event | null; + }; +} diff --git a/resources/js/types/event.d.ts b/resources/js/types/event.d.ts index 43de918f..e5ff024c 100644 --- a/resources/js/types/event.d.ts +++ b/resources/js/types/event.d.ts @@ -16,5 +16,6 @@ declare namespace App.Models { registrations?: Registration[] | null; slots?: Slot[] | null; stations?: Station[] | null; + courses?: Course[] | null; }; }