$subEvents Sub-events keyed 0..n in date order */ public static function seedForFestival(Organisation $org, Event $festival, array $subEvents): void { if (count($subEvents) < 3) { return; } // Genres $genres = collect([ ['name' => 'Hardstyle', 'color' => '#e85d75'], ['name' => 'Techno', 'color' => '#1f6feb'], ['name' => 'Indie', 'color' => '#7c3aed'], ['name' => 'Live band', 'color' => '#0ea5e9'], ])->mapWithKeys(fn (array $g) => [ $g['name'] => Genre::create([ 'organisation_id' => $org->id, 'name' => $g['name'], 'color' => $g['color'], 'sort_order' => 0, 'is_active' => true, ]), ]); // Stages on the festival $stages = collect([ ['name' => 'Mainstage', 'color' => '#e85d75', 'capacity' => 4500, 'sort_order' => 1], ['name' => 'Havana', 'color' => '#0ea5e9', 'capacity' => 1200, 'sort_order' => 2], ['name' => 'Stairway', 'color' => '#7c3aed', 'capacity' => 800, 'sort_order' => 3], ['name' => 'Socialite', 'color' => '#22c55e', 'capacity' => 600, 'sort_order' => 4], ])->mapWithKeys(fn (array $s) => [ $s['name'] => Stage::create(['event_id' => $festival->id, ...$s]), ]); // stage_days — every stage active every sub-event day foreach ($stages as $stage) { foreach ($subEvents as $subEvent) { StageDay::create([ 'stage_id' => $stage->id, 'event_id' => $subEvent->id, ]); } } // Master artists $artistsData = [ ['name' => 'Donker & Licht', 'genre' => 'Hardstyle', 'draw' => 3500, 'star' => 5], ['name' => 'Voltage Collective', 'genre' => 'Techno', 'draw' => 1800, 'star' => 4], ['name' => 'Roos & de Wolf', 'genre' => 'Indie', 'draw' => 700, 'star' => 3], ['name' => 'Rotterdam Brass', 'genre' => 'Live band', 'draw' => 900, 'star' => 4], ['name' => 'Nachtwacht DJs', 'genre' => 'Techno', 'draw' => 1100, 'star' => 3], ['name' => 'De Lichtbrigade', 'genre' => 'Live band', 'draw' => 500, 'star' => 3], ]; $artists = []; foreach ($artistsData as $data) { /** @var Artist $artist */ $artist = Artist::create([ 'organisation_id' => $org->id, 'name' => $data['name'], 'default_genre_id' => $genres[$data['genre']]->id, 'default_draw' => $data['draw'], 'star_rating' => $data['star'], 'home_base_country' => 'NL', ]); $artists[$data['name']] = $artist; ArtistContact::create([ 'artist_id' => $artist->id, 'name' => 'Tour Manager '.$artist->name, 'email' => 'tm-'.$artist->slug.'@example.test', 'phone' => '+31612340000', 'role' => 'tour_manager', 'is_primary' => true, 'receives_briefing' => true, 'receives_infosheet' => true, ]); } // Engagements (12) — status mix per RFC §5.3 Session 1 prompt. // Two artists get two engagements (different days) to exercise D17. $statusPlan = [ ['artist' => 'Donker & Licht', 'sub' => 0, 'status' => ArtistEngagementStatus::Contracted], ['artist' => 'Donker & Licht', 'sub' => 1, 'status' => ArtistEngagementStatus::Contracted], ['artist' => 'Voltage Collective', 'sub' => 0, 'status' => ArtistEngagementStatus::Confirmed], ['artist' => 'Voltage Collective', 'sub' => 1, 'status' => ArtistEngagementStatus::Option], ['artist' => 'Roos & de Wolf', 'sub' => 1, 'status' => ArtistEngagementStatus::Contracted], ['artist' => 'Rotterdam Brass', 'sub' => 0, 'status' => ArtistEngagementStatus::Confirmed], ['artist' => 'Rotterdam Brass', 'sub' => 2, 'status' => ArtistEngagementStatus::Requested], ['artist' => 'Nachtwacht DJs', 'sub' => 1, 'status' => ArtistEngagementStatus::Option], ['artist' => 'Nachtwacht DJs', 'sub' => 2, 'status' => ArtistEngagementStatus::Cancelled], ['artist' => 'De Lichtbrigade', 'sub' => 0, 'status' => ArtistEngagementStatus::Draft], ['artist' => 'De Lichtbrigade', 'sub' => 1, 'status' => ArtistEngagementStatus::Requested], ['artist' => 'De Lichtbrigade', 'sub' => 2, 'status' => ArtistEngagementStatus::Option], ]; $engagements = []; foreach ($statusPlan as $idx => $plan) { /** @var Event $subEvent */ $subEvent = $subEvents[$plan['sub']]; $artist = $artists[$plan['artist']]; $attrs = [ 'artist_id' => $artist->id, 'event_id' => $subEvent->id, 'booking_status' => $plan['status'], 'fee_currency' => 'EUR', 'buma_applicable' => true, 'buma_percentage' => 7.00, 'buma_handled_by' => 'organisation', 'vat_applicable' => true, 'vat_percentage' => 21.00, 'payment_status' => 'none', 'crew_count' => 2, 'guests_count' => 4, 'advancing_completed_count' => 0, 'advancing_total_count' => 0, ]; if ($plan['status'] === ArtistEngagementStatus::Option) { $attrs['option_expires_at'] = CarbonImmutable::now()->addDays(14); } if ($plan['status'] === ArtistEngagementStatus::Requested) { $attrs['requested_at'] = CarbonImmutable::now()->subDays(3); } if ($plan['status'] === ArtistEngagementStatus::Contracted) { $attrs['fee_amount'] = 7500.00; } $engagements[$idx] = ArtistEngagement::create($attrs); } // Performances (13) — most engagements get 1 perf, a couple // get 2 (D17). One parked. One B2B pair on Mainstage Saturday. $perfPlan = [ // [engagementIdx, stageName|null, subIdx, hour, minute, duration] [0, 'Mainstage', 0, 22, 0, 75], // Donker & Licht — Vrijdag mainstage [1, 'Mainstage', 1, 23, 30, 60], // Donker & Licht — Zaterdag mainstage (B2B partner-A) [1, 'Mainstage', 1, 21, 0, 60], // …extra perf same engagement (D17 multi-perf) [2, 'Havana', 0, 21, 0, 60], [3, 'Havana', 1, 22, 30, 60], [4, 'Stairway', 1, 21, 0, 75], [5, 'Socialite', 0, 19, 0, 60], [6, 'Socialite', 2, 17, 0, 45], [7, 'Mainstage', 1, 23, 33, 60], // B2B partner-B (3-min offset → seeds B2B detector) [9, null, 0, 0, 0, 60], // De Lichtbrigade Vrijdag = parked / wachtrij [10, 'Stairway', 1, 19, 0, 60], [11, 'Havana', 2, 20, 30, 60], [4, 'Stairway', 1, 22, 30, 60], // multi-perf on same engagement (D17) ]; foreach ($perfPlan as $row) { [$engagementIdx, $stageName, $subIdx, $hour, $minute, $minutes] = $row; $engagement = $engagements[$engagementIdx]; /** @var Event $subEvent */ $subEvent = $subEvents[$subIdx]; $start = CarbonImmutable::parse($subEvent->start_date)->setTime($hour, $minute); Performance::create([ 'engagement_id' => $engagement->id, 'event_id' => $subEvent->id, 'stage_id' => $stageName === null ? null : $stages[$stageName]->id, 'lane' => 0, 'start_at' => $start, 'end_at' => $start->addMinutes($minutes), 'version' => 0, ]); } } }