call(RoleSeeder::class); // 1. Super Admin $admin = User::firstOrCreate( ['email' => 'admin@crewli.test'], [ 'name' => 'Dev Admin', 'password' => Hash::make('password'), ], ); $admin->assignRole('super_admin'); // Test organisation $org = Organisation::firstOrCreate( ['slug' => 'test-festival-bv'], [ 'name' => 'Test Festival BV', 'billing_status' => 'active', 'settings' => [], ], ); // 2. Org Admin $orgAdmin = User::firstOrCreate( ['email' => 'orgadmin@crewli.test'], [ 'name' => 'Org Admin', 'password' => Hash::make('password'), ], ); if (!$org->users()->where('user_id', $orgAdmin->id)->exists()) { $org->users()->attach($orgAdmin, ['role' => 'org_admin']); } // Second test organisation (for testing the organisation switcher) $org2 = Organisation::firstOrCreate( ['slug' => 'zomerfest-nederland'], [ 'name' => 'Zomerfest Nederland', 'billing_status' => 'trial', 'settings' => [], ], ); // Attach admin and orgAdmin to second org too if (!$org2->users()->where('user_id', $admin->id)->exists()) { $org2->users()->attach($admin, ['role' => 'org_admin']); } if (!$org2->users()->where('user_id', $orgAdmin->id)->exists()) { $org2->users()->attach($orgAdmin, ['role' => 'org_member']); } // 3. Org Member $member = User::firstOrCreate( ['email' => 'crew@crewli.test'], [ 'name' => 'Crew Member', 'password' => Hash::make('password'), ], ); if (!$org->users()->where('user_id', $member->id)->exists()) { $org->users()->attach($member, ['role' => 'org_member']); } // 4. Default Crowd Types for Test Festival BV $crowdTypes = [ ['name' => 'Crew', 'system_type' => 'CREW', 'color' => '#3b82f6'], ['name' => 'Vrijwilliger', 'system_type' => 'VOLUNTEER', 'color' => '#10b981'], ['name' => 'Artiest', 'system_type' => 'ARTIST', 'color' => '#8b5cf6'], ['name' => 'Gast', 'system_type' => 'GUEST', 'color' => '#f59e0b'], ['name' => 'Pers', 'system_type' => 'PRESS', 'color' => '#6366f1'], ]; foreach ($crowdTypes as $ct) { CrowdType::firstOrCreate( [ 'organisation_id' => $org->id, 'system_type' => $ct['system_type'], ], [ 'name' => $ct['name'], 'color' => $ct['color'], ], ); } // 5. Flat event (backward compatible single event) Event::firstOrCreate( ['organisation_id' => $org->id, 'slug' => 'test-event-01'], [ 'name' => 'Test Event 01', 'start_date' => '2026-08-15', 'end_date' => '2026-08-15', 'status' => 'draft', 'event_type' => 'event', 'parent_event_id' => null, ], ); // ============================================= // 6. Festival: Echt Feesten 2026 // ============================================= $festival = Event::firstOrCreate( ['organisation_id' => $org->id, 'slug' => 'echt-feesten-2026'], [ 'name' => 'Echt Feesten 2026', 'start_date' => '2026-07-10', 'end_date' => '2026-07-12', 'timezone' => 'Europe/Amsterdam', 'status' => 'registration_open', 'event_type' => 'festival', 'event_type_label' => 'Festival', 'sub_event_label' => 'Programmaonderdeel', 'parent_event_id' => null, ], ); // --- Sub-events --- $vrijdag = Event::firstOrCreate( ['organisation_id' => $org->id, 'slug' => 'echt-feesten-2026-vrijdag'], [ 'name' => 'Vrijdag', 'start_date' => '2026-07-10', 'end_date' => '2026-07-10', 'timezone' => 'Europe/Amsterdam', 'status' => 'registration_open', 'event_type' => 'event', 'parent_event_id' => $festival->id, ], ); Event::firstOrCreate( ['organisation_id' => $org->id, 'slug' => 'echt-feesten-2026-zaterdag'], [ 'name' => 'Zaterdag', 'start_date' => '2026-07-11', 'end_date' => '2026-07-11', 'timezone' => 'Europe/Amsterdam', 'status' => 'registration_open', 'event_type' => 'event', 'parent_event_id' => $festival->id, ], ); Event::firstOrCreate( ['organisation_id' => $org->id, 'slug' => 'echt-feesten-2026-zondag'], [ 'name' => 'Zondag', 'start_date' => '2026-07-12', 'end_date' => '2026-07-12', 'timezone' => 'Europe/Amsterdam', 'status' => 'registration_open', 'event_type' => 'event', 'parent_event_id' => $festival->id, ], ); // --- Festival-level sections (on the parent) --- FestivalSection::firstOrCreate( ['event_id' => $festival->id, 'name' => 'EHBO'], [ 'type' => 'cross_event', 'category' => 'Veiligheid', 'icon' => 'tabler-first-aid-kit', 'sort_order' => 1, 'responder_self_checkin' => true, 'crew_auto_accepts' => false, ], ); FestivalSection::firstOrCreate( ['event_id' => $festival->id, 'name' => 'Nachtsecurity'], [ 'type' => 'standard', 'category' => 'Veiligheid', 'icon' => 'tabler-shield', 'sort_order' => 2, 'responder_self_checkin' => true, 'crew_auto_accepts' => false, ], ); // --- Sub-event sections (on Vrijdag) --- FestivalSection::firstOrCreate( ['event_id' => $vrijdag->id, 'name' => 'Hoofdpodium Bar'], [ 'type' => 'standard', 'category' => 'Bar', 'icon' => 'tabler-beer', 'sort_order' => 1, 'responder_self_checkin' => true, 'crew_auto_accepts' => false, ], ); FestivalSection::firstOrCreate( ['event_id' => $vrijdag->id, 'name' => 'Backstage'], [ 'type' => 'standard', 'category' => 'Hospitality', 'icon' => 'tabler-armchair', 'sort_order' => 2, 'responder_self_checkin' => true, 'crew_auto_accepts' => false, ], ); // --- Festival-level time slots (on the parent) --- TimeSlot::firstOrCreate( ['event_id' => $festival->id, 'name' => 'Opbouw'], [ 'date' => '2026-07-09', 'start_time' => '08:00:00', 'end_time' => '18:00:00', 'duration_hours' => 10.00, 'person_type' => 'CREW', ], ); TimeSlot::firstOrCreate( ['event_id' => $festival->id, 'name' => 'Afbraak'], [ 'date' => '2026-07-13', 'start_time' => '08:00:00', 'end_time' => '18:00:00', 'duration_hours' => 10.00, 'person_type' => 'CREW', ], ); // --- Sub-event time slots (on Vrijdag) --- TimeSlot::firstOrCreate( ['event_id' => $vrijdag->id, 'name' => 'Vrijdag Avond'], [ 'date' => '2026-07-10', 'start_time' => '18:00:00', 'end_time' => '02:00:00', 'duration_hours' => 8.00, 'person_type' => 'VOLUNTEER', ], ); TimeSlot::firstOrCreate( ['event_id' => $vrijdag->id, 'name' => 'Vrijdag Nacht'], [ 'date' => '2026-07-10', 'start_time' => '22:00:00', 'end_time' => '04:00:00', 'duration_hours' => 6.00, 'person_type' => 'CREW', ], ); // --- Festival-level persons (5 volunteers on the parent) --- $volunteerType = CrowdType::where('organisation_id', $org->id) ->where('system_type', 'VOLUNTEER') ->first(); $festivalPersons = [ ['name' => 'Sanne de Vries', 'email' => 'sanne.devries@example.nl', 'phone' => '+31612345001'], ['name' => 'Pieter Jansen', 'email' => 'pieter.jansen@example.nl', 'phone' => '+31612345002'], ['name' => 'Marieke van den Berg', 'email' => 'marieke.vandenberg@example.nl', 'phone' => '+31612345003'], ['name' => 'Thijs Bakker', 'email' => 'thijs.bakker@example.nl', 'phone' => '+31612345004'], // Uses the seeded orgAdmin email to test identity matching later ['name' => 'Org Admin Volunteer', 'email' => 'orgadmin@crewli.test', 'phone' => '+31612345005'], ]; foreach ($festivalPersons as $personData) { Person::firstOrCreate( ['event_id' => $festival->id, 'email' => $personData['email']], [ 'crowd_type_id' => $volunteerType->id, 'name' => $personData['name'], 'phone' => $personData['phone'], 'status' => 'approved', 'is_blacklisted' => false, ], ); } } }