DemoDataSeeder: 6 Spiele, Finanzen, erweiterte Stats und FAQs

5 weitere vergangene Spiele mit vollständigen Spielerstatistiken
(108 Einträge), 51 Finanzeinträge über 2 Saisons, 7 FAQs und
Catering/Zeitnehmer für alle Heimspiele. Toresummen verifiziert.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Rhino
2026-03-02 23:50:49 +01:00
parent f24f7f12a3
commit 0990e4249c

View File

@@ -5,6 +5,8 @@ namespace Database\Seeders;
use App\Enums\CateringStatus; use App\Enums\CateringStatus;
use App\Enums\EventStatus; use App\Enums\EventStatus;
use App\Enums\EventType; use App\Enums\EventType;
use App\Enums\FinanceCategory;
use App\Enums\FinanceType;
use App\Enums\ParticipantStatus; use App\Enums\ParticipantStatus;
use App\Enums\PlayerPosition; use App\Enums\PlayerPosition;
use App\Enums\UserRole; use App\Enums\UserRole;
@@ -18,8 +20,10 @@ use App\Models\EventParticipant;
use App\Models\EventPlayerStat; use App\Models\EventPlayerStat;
use App\Models\EventTimekeeper; use App\Models\EventTimekeeper;
use App\Models\Faq; use App\Models\Faq;
use App\Models\Finance;
use App\Models\Location; use App\Models\Location;
use App\Models\Player; use App\Models\Player;
use App\Models\Season;
use App\Models\Team; use App\Models\Team;
use App\Models\User; use App\Models\User;
use Illuminate\Database\Seeder; use Illuminate\Database\Seeder;
@@ -41,6 +45,7 @@ class DemoDataSeeder extends Seeder
$this->seedParentPlayerRelations($data, $players, $parentUsers); $this->seedParentPlayerRelations($data, $players, $parentUsers);
$this->assignParentRepChild($parentRep, $players); $this->assignParentRepChild($parentRep, $players);
$this->seedSeasons();
$locations = $this->seedLocations(); $locations = $this->seedLocations();
$events = $this->seedEvents($team, $admin, $locations); $events = $this->seedEvents($team, $admin, $locations);
$this->seedParticipants($events, $players, $admin, $parentUsers); $this->seedParticipants($events, $players, $admin, $parentUsers);
@@ -50,6 +55,7 @@ class DemoDataSeeder extends Seeder
$this->seedPlayerStats($events, $players); $this->seedPlayerStats($events, $players);
$this->seedCarpools($events, $parentUsers, $players); $this->seedCarpools($events, $parentUsers, $players);
$this->seedFaqs($admin); $this->seedFaqs($admin);
$this->seedFinances($team, $admin, $coach, $parentRep);
$this->seedActivityLogs($admin, $coach, $team, $events); $this->seedActivityLogs($admin, $coach, $team, $events);
$this->seedSoftDeletedRecords($team); $this->seedSoftDeletedRecords($team);
} }
@@ -425,12 +431,29 @@ class DemoDataSeeder extends Seeder
] ]
); );
// 7: Entwurf // 7: Sonstiges (EventType::Other)
$events[] = Event::updateOrCreate( $events[] = Event::updateOrCreate(
['title' => 'Freundschaftsspiel (in Planung)', 'team_id' => $team->id, 'start_at' => now()->addWeeks(5)->next('Saturday')->setTime(10, 0)], ['title' => 'Trikot-Ausgabe & Mannschaftsfoto', 'team_id' => $team->id, 'start_at' => now()->addWeeks(5)->next('Saturday')->setTime(10, 0)],
[
'type' => EventType::Other,
'end_at' => now()->addWeeks(5)->next('Saturday')->setTime(12, 0),
'status' => EventStatus::Published,
'location_name' => $locations[0]->name,
'address_text' => $locations[0]->address_text,
'location_lat' => $locations[0]->location_lat,
'location_lng' => $locations[0]->location_lng,
'min_players' => 20,
'description_html' => '<p>Neue Trikots werden ausgegeben und wir machen das offizielle <strong>Mannschaftsfoto</strong>!</p><ul><li>Bitte alle pünktlich erscheinen</li><li>Helle Hose mitbringen</li><li>Fotografin kommt um 10:30</li></ul>',
'created_by' => $admin->id,
]
);
// 8: Entwurf
$events[] = Event::updateOrCreate(
['title' => 'Freundschaftsspiel (in Planung)', 'team_id' => $team->id, 'start_at' => now()->addWeeks(6)->next('Saturday')->setTime(10, 0)],
[ [
'type' => EventType::HomeGame, 'type' => EventType::HomeGame,
'end_at' => now()->addWeeks(5)->next('Saturday')->setTime(12, 0), 'end_at' => now()->addWeeks(6)->next('Saturday')->setTime(12, 0),
'status' => EventStatus::Draft, 'status' => EventStatus::Draft,
'location_name' => $locations[0]->name, 'location_name' => $locations[0]->name,
'address_text' => $locations[0]->address_text, 'address_text' => $locations[0]->address_text,
@@ -442,6 +465,112 @@ class DemoDataSeeder extends Seeder
] ]
); );
// 9: Heimspiel (vergangen, 12:10 Sieg)
$events[] = Event::updateOrCreate(
['title' => 'Heimspiel vs. SG Westend', 'team_id' => $team->id, 'start_at' => now()->subWeeks(5)->previous('Saturday')->setTime(10, 0)],
[
'type' => EventType::HomeGame,
'end_at' => now()->subWeeks(5)->previous('Saturday')->setTime(12, 0),
'status' => EventStatus::Published,
'location_name' => $locations[0]->name,
'address_text' => $locations[0]->address_text,
'location_lat' => $locations[0]->location_lat,
'location_lng' => $locations[0]->location_lng,
'opponent' => 'SG Westend',
'score_home' => 12,
'score_away' => 10,
'min_players' => 10,
'min_catering' => 2,
'min_timekeepers' => 2,
'description_html' => '<p>Zweites Heimspiel der Saison. <strong>Wichtig: Hallenschuhe!</strong></p>',
'created_by' => $admin->id,
]
);
// 10: Auswärtsspiel (vergangen, 8:14 Niederlage)
$events[] = Event::updateOrCreate(
['title' => 'Auswärtsspiel bei HSG Bergheim', 'team_id' => $team->id, 'start_at' => now()->subWeeks(4)->previous('Saturday')->setTime(11, 0)],
[
'type' => EventType::AwayGame,
'end_at' => now()->subWeeks(4)->previous('Saturday')->setTime(13, 0),
'status' => EventStatus::Published,
'location_name' => $locations[1]->name,
'address_text' => $locations[1]->address_text,
'location_lat' => $locations[1]->location_lat,
'location_lng' => $locations[1]->location_lng,
'opponent' => 'HSG Bergheim',
'score_home' => 8,
'score_away' => 14,
'min_players' => 10,
'description_html' => '<p>Auswärtsspiel. Treffpunkt <strong>10:00 Uhr</strong> am Parkplatz.</p>',
'created_by' => $admin->id,
]
);
// 11: Heimspiel (vergangen, 11:11 Unentschieden)
$events[] = Event::updateOrCreate(
['title' => 'Heimspiel vs. TV Grüntal', 'team_id' => $team->id, 'start_at' => now()->subWeeks(3)->previous('Saturday')->setTime(10, 0)],
[
'type' => EventType::HomeGame,
'end_at' => now()->subWeeks(3)->previous('Saturday')->setTime(12, 0),
'status' => EventStatus::Published,
'location_name' => $locations[0]->name,
'address_text' => $locations[0]->address_text,
'location_lat' => $locations[0]->location_lat,
'location_lng' => $locations[0]->location_lng,
'opponent' => 'TV Grüntal',
'score_home' => 11,
'score_away' => 11,
'min_players' => 10,
'min_catering' => 2,
'min_timekeepers' => 2,
'description_html' => '<p>Spannendes Spiel erwartet! TV Grüntal steht direkt hinter uns in der Tabelle.</p>',
'created_by' => $admin->id,
]
);
// 12: Auswärtsspiel (vergangen, 13:9 Sieg)
$events[] = Event::updateOrCreate(
['title' => 'Auswärtsspiel bei JSG Adlerhorst', 'team_id' => $team->id, 'start_at' => now()->subDays(18)->setTime(11, 0)],
[
'type' => EventType::AwayGame,
'end_at' => now()->subDays(18)->setTime(13, 0),
'status' => EventStatus::Published,
'location_name' => $locations[2]->name,
'address_text' => $locations[2]->address_text,
'location_lat' => $locations[2]->location_lat,
'location_lng' => $locations[2]->location_lng,
'opponent' => 'JSG Adlerhorst',
'score_home' => 13,
'score_away' => 9,
'min_players' => 10,
'description_html' => '<p>Abfahrt <strong>9:30 Uhr</strong>. Bitte Fahrgemeinschaften bilden.</p>',
'created_by' => $admin->id,
]
);
// 13: Heimspiel (vergangen, 16:14 Sieg)
$events[] = Event::updateOrCreate(
['title' => 'Heimspiel vs. SC Nordpark', 'team_id' => $team->id, 'start_at' => now()->subDays(11)->setTime(10, 0)],
[
'type' => EventType::HomeGame,
'end_at' => now()->subDays(11)->setTime(12, 0),
'status' => EventStatus::Published,
'location_name' => $locations[0]->name,
'address_text' => $locations[0]->address_text,
'location_lat' => $locations[0]->location_lat,
'location_lng' => $locations[0]->location_lng,
'opponent' => 'SC Nordpark',
'score_home' => 16,
'score_away' => 14,
'min_players' => 10,
'min_catering' => 2,
'min_timekeepers' => 2,
'description_html' => '<p>Tabellenführer zu Gast! Bitte alle da sein. <strong>Eltern: Kuchen mitbringen</strong>.</p>',
'created_by' => $admin->id,
]
);
return $events; return $events;
} }
@@ -457,10 +586,15 @@ class DemoDataSeeder extends Seeder
$distributions = [ $distributions = [
0 => [22, 3], // Training vergangen 0 => [22, 3], // Training vergangen
1 => [15, 5], // Training Zukunft 1 => [15, 5], // Training Zukunft
2 => [18, 4], // Heimspiel 2 => [18, 4], // Heimspiel vs TSV Beispielburg
3 => [12, 3], // Auswärtsspiel 3 => [12, 3], // Auswärtsspiel
4 => [20, 2], // Turnier 4 => [20, 2], // Turnier
6 => [5, 2], // Abgesagt 6 => [5, 2], // Abgesagt
9 => [20, 3], // Heimspiel vs SG Westend
10 => [14, 6], // Auswärtsspiel bei HSG Bergheim
11 => [18, 4], // Heimspiel vs TV Grüntal
12 => [16, 5], // Auswärtsspiel bei JSG Adlerhorst
13 => [22, 2], // Heimspiel vs SC Nordpark
]; ];
$sampleNotes = [ $sampleNotes = [
@@ -526,6 +660,16 @@ class DemoDataSeeder extends Seeder
[$events[4]->id, $p[5]->id, CateringStatus::Yes, 'Kuchen und Muffins'], [$events[4]->id, $p[5]->id, CateringStatus::Yes, 'Kuchen und Muffins'],
[$events[4]->id, $p[6]->id, CateringStatus::Yes, 'Getränke'], [$events[4]->id, $p[6]->id, CateringStatus::Yes, 'Getränke'],
[$events[4]->id, $p[7]->id, CateringStatus::No, null], [$events[4]->id, $p[7]->id, CateringStatus::No, null],
// Heimspiel vs SG Westend (9)
[$events[9]->id, $p[2]->id, CateringStatus::Yes, 'Apfelkuchen'],
[$events[9]->id, $p[4]->id, CateringStatus::Yes, 'Wasser und Saft'],
// Heimspiel vs TV Grüntal (11)
[$events[11]->id, $p[6]->id, CateringStatus::Yes, 'Obstteller'],
[$events[11]->id, $p[8]->id, CateringStatus::Yes, 'Brezeln und Laugenbrötchen'],
// Heimspiel vs SC Nordpark (13)
[$events[13]->id, $p[1]->id, CateringStatus::Yes, 'Pizzaschnecken'],
[$events[13]->id, $p[3]->id, CateringStatus::Yes, 'Gemüse-Sticks und Dip'],
[$events[13]->id, $p[9]->id, CateringStatus::Yes, 'Getränke'],
]; ];
foreach ($entries as [$eventId, $userId, $status, $note]) { foreach ($entries as [$eventId, $userId, $status, $note]) {
@@ -554,6 +698,15 @@ class DemoDataSeeder extends Seeder
[$events[1]->id, $p[13]->id, CateringStatus::No], [$events[1]->id, $p[13]->id, CateringStatus::No],
[$events[4]->id, $p[14]->id, CateringStatus::Yes], [$events[4]->id, $p[14]->id, CateringStatus::Yes],
[$events[4]->id, $p[15]->id, CateringStatus::Unknown], [$events[4]->id, $p[15]->id, CateringStatus::Unknown],
// Heimspiel vs SG Westend (9)
[$events[9]->id, $p[8]->id, CateringStatus::Yes],
[$events[9]->id, $p[9]->id, CateringStatus::Yes],
// Heimspiel vs TV Grüntal (11)
[$events[11]->id, $p[10]->id, CateringStatus::Yes],
[$events[11]->id, $p[12]->id, CateringStatus::Yes],
// Heimspiel vs SC Nordpark (13)
[$events[13]->id, $p[14]->id, CateringStatus::Yes],
[$events[13]->id, $p[11]->id, CateringStatus::Yes],
]; ];
foreach ($entries as [$eventId, $userId, $status]) { foreach ($entries as [$eventId, $userId, $status]) {
@@ -631,52 +784,166 @@ class DemoDataSeeder extends Seeder
} }
// ─── Spielerstatistiken ───────────────────────────────── // ─── Spielerstatistiken ─────────────────────────────────
// Heimspiel (Index 2, Ergebnis 15:12) — Stats für zugesagte Spieler // Stats für 6 vergangene Spiele (Index 2, 9, 10, 11, 12, 13)
private function seedPlayerStats(array $events, array $players): void private function seedPlayerStats(array $events, array $players): void
{ {
$homeGame = $events[2]; // Heimspiel vs. TSV Beispielburg (15:12)
$playerList = array_values($players); $playerList = array_values($players);
// Nur die ersten 18 Spieler haben beim Heimspiel zugesagt (siehe seedParticipants) // Format: [index, is_gk, gk_saves, gk_shots, goals, shots, pen_goals, pen_shots, yellow, two_min, minutes, note, position]
$statsData = [ $allStats = [
// [index, is_goalkeeper, gk_saves, gk_shots, goals, shots, note, position] // Spiel 2: Heimspiel vs TSV Beispielburg (15:12 Sieg)
[0, true, 8, 20, 0, 0, 'Starke Leistung im Tor', 'torwart'], 2 => [
[1, false, null, null, 3, 6, 'Drei Tempogegenstöße', 'links_aussen'], [0, true, 8, 20, 0, 0, null, null, 0, 0, 60, 'Starke Leistung im Tor', 'torwart'],
[2, false, null, null, 2, 5, 'Guter Aufbau', 'rueckraum_mitte'], [1, false, null, null, 3, 6, 1, 2, 0, 0, 55, 'Drei Tempogegenstöße', 'links_aussen'],
[3, false, null, null, 2, 4, null, 'rueckraum_links'], [2, false, null, null, 2, 5, 0, 1, 1, 0, 50, 'Guter Aufbau', 'rueckraum_mitte'],
[4, false, null, null, 1, 3, 'Schnelle Beine', 'rechts_aussen'], [3, false, null, null, 2, 4, 1, 1, 0, 0, 50, null, 'rueckraum_links'],
[5, false, null, null, 2, 5, null, 'rueckraum_rechts'], [4, false, null, null, 1, 3, 0, 0, 0, 0, 45, 'Schnelle Beine', 'rechts_aussen'],
[6, false, null, null, 1, 2, 'Erste Tore der Saison!', 'kreislaeufer'], [5, false, null, null, 2, 5, 0, 0, 0, 1, 50, null, 'rueckraum_rechts'],
[7, false, null, null, 1, 4, null, 'links_aussen'], [6, false, null, null, 1, 2, 0, 0, 0, 0, 40, 'Erste Tore der Saison!', 'kreislaeufer'],
[8, false, null, null, 1, 3, null, 'rechts_aussen'], [7, false, null, null, 1, 4, 0, 0, 1, 0, 35, null, 'links_aussen'],
[9, false, null, null, 1, 2, null, 'rueckraum_links'], [8, false, null, null, 1, 3, 0, 0, 0, 0, 40, null, 'rechts_aussen'],
[10, false, null, null, 1, 3, 'Stark in der Abwehr', 'rueckraum_mitte'], [9, false, null, null, 1, 2, 0, 0, 0, 0, 30, null, 'rueckraum_links'],
[11, false, null, null, 0, 2, null, 'rueckraum_rechts'], [10, false, null, null, 1, 3, 0, 0, 0, 0, 45, 'Stark in der Abwehr', 'rueckraum_mitte'],
[12, false, null, null, 0, 1, null, 'kreislaeufer'], [11, false, null, null, 0, 2, 0, 0, 0, 0, 25, null, 'rueckraum_rechts'],
[13, false, null, null, 0, 1, null, 'torwart'], [12, false, null, null, 0, 1, 0, 0, 0, 0, 20, null, 'kreislaeufer'],
[14, false, null, null, 0, 2, 'Erste Spielminuten', null], [13, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, 'torwart'],
[15, false, null, null, 0, 0, null, null], [14, false, null, null, 0, 2, 0, 0, 0, 0, 20, 'Erste Spielminuten', null],
[16, false, null, null, 0, 1, null, null], [15, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
[17, false, null, null, 0, 0, null, null], [16, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
[17, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
],
// Spiel 9: Heimspiel vs SG Westend (12:10 Sieg)
9 => [
[0, true, 10, 22, 0, 0, null, null, 0, 0, 60, 'Überragend gehalten', 'torwart'],
[1, false, null, null, 2, 5, 0, 1, 0, 0, 55, null, 'links_aussen'],
[2, false, null, null, 3, 7, 2, 3, 0, 0, 55, 'Bester Werfer', 'rueckraum_mitte'],
[3, false, null, null, 1, 3, 0, 0, 1, 0, 45, null, 'rueckraum_links'],
[4, false, null, null, 1, 4, 0, 0, 0, 0, 50, null, 'rechts_aussen'],
[5, false, null, null, 2, 4, 0, 0, 0, 0, 50, null, 'rueckraum_rechts'],
[6, false, null, null, 1, 2, 0, 0, 0, 1, 40, null, 'kreislaeufer'],
[7, false, null, null, 0, 3, 0, 0, 0, 0, 30, null, 'links_aussen'],
[8, false, null, null, 1, 2, 0, 0, 0, 0, 35, null, 'rechts_aussen'],
[9, false, null, null, 0, 1, 0, 0, 0, 0, 25, null, 'rueckraum_links'],
[10, false, null, null, 1, 3, 0, 0, 0, 0, 40, null, 'rueckraum_mitte'],
[11, false, null, null, 0, 1, 0, 0, 0, 0, 20, null, 'rueckraum_rechts'],
[12, false, null, null, 0, 2, 0, 0, 0, 0, 25, null, 'kreislaeufer'],
[13, false, null, null, 0, 0, 0, 0, 0, 0, 15, null, null],
[14, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
[15, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
[16, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
[17, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
[18, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
[19, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
],
// Spiel 10: Auswärtsspiel bei HSG Bergheim (8:14 Niederlage)
10 => [
[0, true, 5, 22, 0, 0, null, null, 0, 0, 60, 'Schwieriger Tag', 'torwart'],
[1, false, null, null, 2, 6, 1, 2, 0, 1, 50, null, 'links_aussen'],
[2, false, null, null, 1, 5, 0, 0, 1, 0, 50, null, 'rueckraum_mitte'],
[3, false, null, null, 1, 4, 0, 1, 0, 0, 45, null, 'rueckraum_links'],
[4, false, null, null, 1, 3, 0, 0, 0, 0, 45, null, 'rechts_aussen'],
[5, false, null, null, 1, 4, 0, 0, 1, 1, 40, '2-Min wegen Foul', 'rueckraum_rechts'],
[6, false, null, null, 1, 3, 0, 0, 0, 0, 35, null, 'kreislaeufer'],
[7, false, null, null, 0, 2, 0, 0, 0, 0, 30, null, 'links_aussen'],
[8, false, null, null, 1, 3, 0, 0, 0, 0, 35, null, 'rechts_aussen'],
[9, false, null, null, 0, 2, 0, 0, 0, 0, 25, null, 'rueckraum_links'],
[10, false, null, null, 0, 2, 0, 0, 0, 0, 35, null, 'rueckraum_mitte'],
[13, true, 3, 8, 0, 0, null, null, 0, 0, 20, 'Ersatz-TW 2. Halbzeit', 'torwart'],
[11, false, null, null, 0, 1, 0, 0, 0, 0, 20, null, 'kreislaeufer'],
[14, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
],
// Spiel 11: Heimspiel vs TV Grüntal (11:11 Unentschieden)
11 => [
[0, true, 9, 22, 0, 0, null, null, 0, 0, 60, 'Klasse gehalten', 'torwart'],
[1, false, null, null, 2, 5, 1, 1, 0, 0, 55, null, 'links_aussen'],
[2, false, null, null, 2, 6, 0, 1, 0, 0, 55, null, 'rueckraum_mitte'],
[3, false, null, null, 2, 4, 1, 2, 0, 0, 50, 'Starke 7-Meter', 'rueckraum_links'],
[4, false, null, null, 1, 3, 0, 0, 0, 0, 45, null, 'rechts_aussen'],
[5, false, null, null, 1, 4, 0, 0, 0, 0, 50, null, 'rueckraum_rechts'],
[6, false, null, null, 1, 2, 0, 0, 1, 0, 40, null, 'kreislaeufer'],
[7, false, null, null, 1, 3, 0, 0, 0, 0, 35, null, 'links_aussen'],
[8, false, null, null, 0, 2, 0, 0, 0, 0, 30, null, 'rechts_aussen'],
[9, false, null, null, 0, 1, 0, 0, 0, 0, 25, null, 'rueckraum_links'],
[10, false, null, null, 1, 2, 0, 0, 0, 0, 40, null, 'rueckraum_mitte'],
[11, false, null, null, 0, 1, 0, 0, 0, 0, 20, null, 'rueckraum_rechts'],
[12, false, null, null, 0, 2, 0, 0, 0, 0, 25, null, 'kreislaeufer'],
[13, false, null, null, 0, 0, 0, 0, 0, 0, 15, null, null],
[14, false, null, null, 0, 1, 0, 0, 0, 0, 20, null, null],
[15, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
[16, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
[17, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
],
// Spiel 12: Auswärtsspiel bei JSG Adlerhorst (13:9 Sieg)
12 => [
[0, true, 11, 20, 0, 0, null, null, 0, 0, 60, 'Bestes Spiel der Saison!', 'torwart'],
[1, false, null, null, 3, 5, 2, 2, 0, 0, 55, 'Perfekte 7-Meter-Quote', 'links_aussen'],
[2, false, null, null, 2, 4, 0, 0, 0, 0, 50, null, 'rueckraum_mitte'],
[3, false, null, null, 2, 4, 0, 0, 0, 0, 50, null, 'rueckraum_links'],
[4, false, null, null, 2, 4, 0, 0, 0, 0, 50, 'Doppelpack!', 'rechts_aussen'],
[5, false, null, null, 1, 3, 0, 0, 0, 0, 45, null, 'rueckraum_rechts'],
[6, false, null, null, 1, 2, 0, 0, 0, 0, 40, null, 'kreislaeufer'],
[7, false, null, null, 1, 3, 0, 0, 1, 0, 35, null, 'links_aussen'],
[8, false, null, null, 0, 2, 0, 0, 0, 0, 30, null, 'rechts_aussen'],
[9, false, null, null, 1, 2, 0, 0, 0, 0, 30, null, 'rueckraum_links'],
[10, false, null, null, 0, 2, 0, 0, 0, 0, 35, null, 'rueckraum_mitte'],
[11, false, null, null, 0, 1, 0, 0, 0, 0, 20, null, 'rueckraum_rechts'],
[12, false, null, null, 0, 1, 0, 0, 0, 0, 20, null, 'kreislaeufer'],
[13, false, null, null, 0, 0, 0, 0, 0, 0, 15, null, null],
[14, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
[15, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
],
// Spiel 13: Heimspiel vs SC Nordpark (16:14 Sieg)
13 => [
[0, true, 7, 24, 0, 0, null, null, 0, 0, 50, null, 'torwart'],
[13, true, 4, 10, 0, 0, null, null, 0, 0, 20, 'Guter Einsatz als Ersatz-TW', 'torwart'],
[1, false, null, null, 4, 7, 2, 3, 0, 0, 55, 'Überragend!', 'links_aussen'],
[2, false, null, null, 3, 6, 1, 1, 0, 0, 55, null, 'rueckraum_mitte'],
[3, false, null, null, 2, 5, 0, 0, 0, 1, 50, null, 'rueckraum_links'],
[4, false, null, null, 2, 4, 0, 0, 0, 0, 50, null, 'rechts_aussen'],
[5, false, null, null, 1, 4, 0, 0, 1, 0, 50, null, 'rueckraum_rechts'],
[6, false, null, null, 1, 3, 0, 0, 0, 0, 45, null, 'kreislaeufer'],
[7, false, null, null, 1, 2, 0, 0, 0, 0, 35, null, 'links_aussen'],
[8, false, null, null, 1, 3, 0, 0, 0, 0, 40, null, 'rechts_aussen'],
[9, false, null, null, 0, 2, 0, 0, 0, 0, 30, null, 'rueckraum_links'],
[10, false, null, null, 1, 3, 0, 0, 0, 0, 45, null, 'rueckraum_mitte'],
[11, false, null, null, 0, 1, 0, 0, 0, 0, 25, null, 'rueckraum_rechts'],
[12, false, null, null, 0, 2, 0, 0, 0, 0, 25, null, 'kreislaeufer'],
[14, false, null, null, 0, 1, 0, 0, 0, 0, 20, null, null],
[15, false, null, null, 0, 0, 0, 0, 0, 0, 15, null, null],
[16, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
[17, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
[18, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
[19, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
[20, false, null, null, 0, 0, 0, 0, 0, 0, 10, null, null],
[21, false, null, null, 0, 1, 0, 0, 0, 0, 15, null, null],
],
]; ];
foreach ($statsData as [$idx, $isGk, $gkSaves, $gkShots, $goals, $shots, $note, $position]) { foreach ($allStats as $eventIdx => $statsData) {
if (!isset($playerList[$idx])) { $event = $events[$eventIdx];
continue; foreach ($statsData as [$idx, $isGk, $gkSaves, $gkShots, $goals, $shots, $penGoals, $penShots, $yellow, $twoMin, $minutes, $note, $position]) {
if (!isset($playerList[$idx])) {
continue;
}
EventPlayerStat::updateOrCreate(
['event_id' => $event->id, 'player_id' => $playerList[$idx]->id],
[
'is_goalkeeper' => $isGk,
'goalkeeper_saves' => $gkSaves,
'goalkeeper_shots' => $gkShots,
'goals' => $goals,
'shots' => $shots,
'penalty_goals' => $penGoals,
'penalty_shots' => $penShots,
'yellow_cards' => $yellow,
'two_minute_suspensions' => $twoMin,
'playing_time_minutes' => $minutes,
'note' => $note,
'position' => $position,
]
);
} }
EventPlayerStat::updateOrCreate(
['event_id' => $homeGame->id, 'player_id' => $playerList[$idx]->id],
[
'is_goalkeeper' => $isGk,
'goalkeeper_saves' => $gkSaves,
'goalkeeper_shots' => $gkShots,
'goals' => $goals,
'shots' => $shots,
'note' => $note,
'position' => $position,
]
);
} }
} }
@@ -751,9 +1018,13 @@ class DemoDataSeeder extends Seeder
private function seedFaqs(User $admin): void private function seedFaqs(User $admin): void
{ {
$faqs = [ $faqs = [
['title' => 'Wie melde ich mein Kind für ein Event an?', 'content_html' => '<p>Gehe auf die Event-Detailseite und klicke bei deinem Kind auf "Zusagen". Du kannst den Status jederzeit ändern.</p>', 'sort_order' => 1], ['title' => 'Wie melde ich mein Kind für ein Event an?', 'content_html' => '<p>Gehe auf die Event-Detailseite und klicke bei deinem Kind auf <strong>"Zusagen"</strong>. Du kannst den Status jederzeit ändern.</p><p>Bitte gib so früh wie möglich Bescheid, damit der Trainer planen kann.</p>', 'sort_order' => 1],
['title' => 'Wie funktioniert das Catering?', 'content_html' => '<p>Bei Heimspielen und Turnieren wird Catering organisiert. Du kannst auf der Event-Seite angeben, ob du etwas mitbringst und was genau.</p>', 'sort_order' => 2], ['title' => 'Wie funktioniert das Catering?', 'content_html' => '<p>Bei Heimspielen und Turnieren wird Catering organisiert. Du kannst auf der Event-Seite angeben, ob du etwas mitbringst und was genau.</p><p>Typische Beiträge sind Kuchen, Obst, Getränke oder belegte Brötchen.</p>', 'sort_order' => 2],
['title' => 'Was ist ein Zeitnehmer?', 'content_html' => '<p>Bei Heimspielen werden Zeitnehmer benötigt, die die Spieluhr bedienen. Pro Spiel brauchen wir mindestens 2 Zeitnehmer aus den Reihen der Eltern.</p>', 'sort_order' => 3], ['title' => 'Was ist ein Zeitnehmer?', 'content_html' => '<p>Bei Heimspielen werden <strong>Zeitnehmer</strong> benötigt, die die Spieluhr bedienen. Pro Spiel brauchen wir mindestens 2 Zeitnehmer aus den Reihen der Eltern.</p><p>Keine Sorge — es wird vorher eine kurze Einweisung gegeben!</p>', 'sort_order' => 3],
['title' => 'Wie funktionieren Fahrgemeinschaften?', 'content_html' => '<p>Bei Auswärtsspielen und Turnieren können Eltern <strong>Fahrgemeinschaften</strong> anbieten. Gehe auf die Event-Detailseite und trage ein, wie viele Plätze du anbieten kannst.</p><p>Andere Eltern können dann ihre Kinder für die Mitfahrt eintragen.</p>', 'sort_order' => 4],
['title' => 'Wo finde ich die Spielerstatistiken?', 'content_html' => '<p>Im Admin-Bereich unter <strong>"Statistik"</strong> findest du eine Übersicht aller Spieler mit Toren, Würfen und Torwart-Statistiken.</p><p>Die Statistiken können nach Saison, Zeitraum und Team gefiltert werden.</p>', 'sort_order' => 5],
['title' => 'Kann ich mein Profil bearbeiten?', 'content_html' => '<p>Ja! Klicke oben rechts auf deinen Namen und dann auf <strong>"Profil"</strong>. Dort kannst du:</p><ul><li>Deinen Namen und Telefonnummer ändern</li><li>Ein Profilbild hochladen</li><li>Dein Passwort ändern</li><li>Die Sprache der App umstellen</li></ul>', 'sort_order' => 6],
['title' => 'Was passiert wenn ich absage?', 'content_html' => '<p>Kein Problem! Absagen sind wichtig, damit der Trainer rechtzeitig planen kann. Bitte sage so früh wie möglich ab.</p><p>Du kannst auch eine <strong>Notiz</strong> hinterlassen (z.B. "krank" oder "Familienfeier").</p>', 'sort_order' => 7],
]; ];
foreach ($faqs as $data) { foreach ($faqs as $data) {
@@ -790,6 +1061,10 @@ class DemoDataSeeder extends Seeder
['user_id' => $admin->id, 'action' => 'updated', 'model_type' => 'Event', 'model_id' => $events[6]->id, 'description' => 'Event abgesagt', 'properties' => ['old' => ['status' => 'published'], 'new' => ['status' => 'cancelled']], 'ip_address' => '127.0.0.1', 'created_at' => $base->copy()->addDays(4)], ['user_id' => $admin->id, 'action' => 'updated', 'model_type' => 'Event', 'model_id' => $events[6]->id, 'description' => 'Event abgesagt', 'properties' => ['old' => ['status' => 'published'], 'new' => ['status' => 'cancelled']], 'ip_address' => '127.0.0.1', 'created_at' => $base->copy()->addDays(4)],
['user_id' => $admin->id, 'action' => 'deleted', 'model_type' => 'User', 'description' => 'Benutzer gelöscht (Soft-Delete)', 'ip_address' => '127.0.0.1', 'created_at' => $base->copy()->addDays(5)], ['user_id' => $admin->id, 'action' => 'deleted', 'model_type' => 'User', 'description' => 'Benutzer gelöscht (Soft-Delete)', 'ip_address' => '127.0.0.1', 'created_at' => $base->copy()->addDays(5)],
['user_id' => $admin->id, 'action' => 'created', 'model_type' => 'File', 'description' => 'Datei "Regelwerk_Handball.pdf" hochgeladen', 'ip_address' => '127.0.0.1', 'created_at' => $base->copy()->addDays(6)], ['user_id' => $admin->id, 'action' => 'created', 'model_type' => 'File', 'description' => 'Datei "Regelwerk_Handball.pdf" hochgeladen', 'ip_address' => '127.0.0.1', 'created_at' => $base->copy()->addDays(6)],
['user_id' => $admin->id, 'action' => 'season_created', 'model_type' => 'Season', 'description' => 'Saison "2025/2026" erstellt', 'ip_address' => '127.0.0.1', 'created_at' => $base->copy()->addDays(6)->addHours(2)],
['user_id' => $admin->id, 'action' => 'finance_created', 'model_type' => 'Finance', 'description' => 'income: Hauptsponsor Saison 2025/2026', 'ip_address' => '127.0.0.1', 'created_at' => $base->copy()->addDays(6)->addHours(3)],
['user_id' => $coach->id, 'action' => 'finance_created', 'model_type' => 'Finance', 'description' => 'expense: Neue Handbälle (10 Stück)', 'ip_address' => '192.168.1.50', 'created_at' => $base->copy()->addDays(6)->addHours(4)],
['user_id' => $admin->id, 'action' => 'finance_updated', 'model_type' => 'Finance', 'description' => 'income: Hauptsponsor Saison 2025/2026', 'properties' => ['before' => ['amount' => 80000], 'after' => ['amount' => 100000]], 'ip_address' => '127.0.0.1', 'created_at' => $base->copy()->addDays(6)->addHours(5)],
]; ];
foreach ($logs as $log) { foreach ($logs as $log) {
@@ -850,4 +1125,118 @@ class DemoDataSeeder extends Seeder
return "{$f}.{$l}@handball.local"; return "{$f}.{$l}@handball.local";
} }
// ─── Saisons ──────────────────────────────────────────
private function seedSeasons(): void
{
Season::firstOrCreate(
['name' => '2024/2025'],
['start_date' => '2024-09-01', 'end_date' => '2025-06-30', 'is_current' => false]
);
Season::firstOrCreate(
['name' => '2025/2026'],
['start_date' => '2025-09-01', 'end_date' => '2026-06-30', 'is_current' => true]
);
}
// ─── Finanzen ─────────────────────────────────────────
private function seedFinances(Team $team, User $admin, User $coach, User $parentRep): void
{
// [type, category, title, amount_cents, date, created_by, team_id (null=übergreifend), notes]
$entries = [
// ─── Saison 2024/2025 (Vorjahr) ─────────────────────────
// Einnahmen
['income', 'sponsoring', 'Hauptsponsor Saison 2024/2025', 80000, '2024-09-01', $admin->id, $team->id, 'Vertrag über 2 Jahre'],
['income', 'membership', 'Mitgliedsbeiträge Herbst 2024', 52000, '2024-10-01', $admin->id, $team->id, null],
['income', 'catering', 'Catering Heimspiel vs. SG Westend', 9500, '2024-10-19', $parentRep->id, $team->id, 'Kuchen + Getränke'],
['income', 'catering', 'Kuchenverkauf Adventsturnier', 15500, '2024-12-07', $parentRep->id, $team->id, null],
['income', 'events', 'Eintritt Weihnachtsfeier 2024', 12000, '2024-12-21', $coach->id, $team->id, null],
['income', 'membership', 'Mitgliedsbeiträge Frühjahr 2025', 52000, '2025-01-15', $admin->id, $team->id, null],
['income', 'sponsoring', 'Bandenwerbung Sporthalle', 25000, '2025-02-01', $admin->id, null, 'Vereinsübergreifend'],
['income', 'tournament_fees', 'Startgeld-Rückerstattung Turnier', 3500, '2025-03-10', $coach->id, $team->id, 'Turnier abgesagt, Erstattung erhalten'],
['income', 'catering', 'Catering Heimspiel vs. TV Grünberg', 8200, '2025-04-05', $parentRep->id, $team->id, null],
['income', 'other', 'Spende Elternschaft', 20000, '2025-05-20', $admin->id, $team->id, 'Für neue Trikots'],
// Ausgaben
['expense', 'venue_rental', 'Hallenmiete Sep-Dez 2024', 72000, '2024-09-15', $admin->id, $team->id, '4 Monate à 180€'],
['expense', 'equipment', 'Handbälle Größe 0 (12 Stück)', 17940, '2024-09-20', $coach->id, $team->id, 'Select Solera'],
['expense', 'training_material','Koordinationsleiter + Hütchen-Set', 5990, '2024-10-05', $coach->id, $team->id, null],
['expense', 'tournament_fees', 'Anmeldegebühr Adventsturnier', 5000, '2024-11-01', $coach->id, $team->id, null],
['expense', 'transport', 'Busfahrt Auswärtsspiel Bergheim', 28000, '2024-11-16', $admin->id, $team->id, null],
['expense', 'venue_rental', 'Hallenmiete Jan-Jun 2025', 108000, '2025-01-10', $admin->id, $team->id, '6 Monate à 180€'],
['expense', 'equipment', 'Tornetze Ersatz (2 Stück)', 12500, '2025-02-15', $admin->id, $team->id, null],
['expense', 'other', 'Schiedsrichterkosten Rückrunde', 9000, '2025-03-01', $admin->id, $team->id, '6 Heimspiele à 15€'],
['expense', 'transport', 'Fahrtkostenzuschuss Trainer', 15000, '2025-04-01', $admin->id, null, 'Vereinsübergreifend, monatlich'],
['expense', 'events', 'Saisonabschlussfeier 2024/2025', 22000, '2025-06-28', $parentRep->id, $team->id, 'Grillpaket + Getränke'],
// ─── Saison 2025/2026 (aktuell) ──────────────────────────
// Einnahmen — September
['income', 'sponsoring', 'Hauptsponsor Saison 2025/2026', 100000, '2025-09-01', $admin->id, $team->id, 'Vertrag verlängert, +200€'],
['income', 'sponsoring', 'Trikotsponsoring Autohaus Schmidt', 30000, '2025-09-15', $admin->id, $team->id, null],
['income', 'membership', 'Mitgliedsbeiträge Herbst 2025', 58000, '2025-09-20', $admin->id, $team->id, '29 Spieler à 20€'],
// Einnahmen — Oktober
['income', 'catering', 'Catering Heimspiel vs. HSG Musterstadt', 8500, '2025-10-12', $parentRep->id, $team->id, 'Kuchen + Kaffee'],
['income', 'other', 'Spende Förderverein', 15000, '2025-10-15', $admin->id, null, 'Vereinsübergreifende Förderung'],
// Einnahmen — November
['income', 'catering', 'Kuchenverkauf Herbstturnier', 12050, '2025-11-15', $parentRep->id, $team->id, 'Rekord! 24 Kuchen verkauft'],
['income', 'catering', 'Catering Heimspiel vs. TV Adler', 7200, '2025-11-23', $parentRep->id, $team->id, null],
// Einnahmen — Dezember
['income', 'events', 'Einnahmen Weihnachtsfeier', 18500, '2025-12-20', $coach->id, $team->id, 'Tombola + Getränkeverkauf'],
['income', 'sponsoring', 'Weihnachtsspende Bäckerei Müller', 10000, '2025-12-22', $admin->id, $team->id, null],
// Einnahmen — Januar/Februar 2026
['income', 'membership', 'Mitgliedsbeiträge Frühjahr 2026', 58000, '2026-01-10', $admin->id, $team->id, null],
['income', 'catering', 'Catering Heimspiel vs. SC Nordpark', 6800, '2026-01-25', $parentRep->id, $team->id, null],
['income', 'tournament_fees', 'Startgeld Hallenturnier (Veranstalter)', 24000, '2026-02-08', $coach->id, $team->id, '8 Teams à 30€'],
['income', 'catering', 'Kuchenverkauf Hallenturnier', 19500, '2026-02-08', $parentRep->id, $team->id, 'Ganztagesturnier — sehr guter Umsatz'],
// Ausgaben — September
['expense', 'equipment', 'Trikotdruck Rückennummern', 18500, '2025-09-05', $admin->id, $team->id, 'Satz Heim + Auswärts'],
['expense', 'equipment', 'Neue Handbälle (10 Stück)', 24990, '2025-09-10', $coach->id, $team->id, 'Select Solera Größe 0'],
['expense', 'training_material','Hütchen, Leibchen, Koordinationsleiter', 4500, '2025-09-20', $coach->id, $team->id, null],
['expense', 'venue_rental', 'Hallenmiete September 2025', 18000, '2025-09-25', $admin->id, $team->id, null],
// Ausgaben — Oktober
['expense', 'venue_rental', 'Hallenmiete Oktober 2025', 18000, '2025-10-01', $admin->id, $team->id, null],
['expense', 'tournament_fees', 'Teilnahme Herbstcup', 7500, '2025-10-20', $coach->id, $team->id, null],
['expense', 'transport', 'Busfahrt Auswärtsspiel Musterstadt', 32000, '2025-10-26', $admin->id, $team->id, 'Reisebus 50 Plätze'],
// Ausgaben — November
['expense', 'venue_rental', 'Hallenmiete November 2025', 18000, '2025-11-01', $admin->id, $team->id, null],
['expense', 'other', 'Schiedsrichterkosten 3 Heimspiele', 6000, '2025-11-30', $admin->id, $team->id, null],
['expense', 'equipment', 'Torwarthandschuhe (2 Paar)', 7980, '2025-11-10', $coach->id, $team->id, 'Kempa Caution'],
// Ausgaben — Dezember
['expense', 'venue_rental', 'Hallenmiete Dezember 2025', 18000, '2025-12-01', $admin->id, $team->id, null],
['expense', 'events', 'Material Weihnachtsfeier', 8500, '2025-12-18', $parentRep->id, $team->id, 'Deko, Geschenke, Nikolaus'],
['expense', 'other', 'Versicherung Vereinshaftpflicht', 35000, '2025-12-15', $admin->id, null, 'Vereinsübergreifend, jährlich'],
// Ausgaben — Januar/Februar 2026
['expense', 'venue_rental', 'Hallenmiete Januar 2026', 18000, '2026-01-05', $admin->id, $team->id, null],
['expense', 'transport', 'Busfahrt Auswärtsspiel Südstadt', 24000, '2026-01-18', $admin->id, $team->id, null],
['expense', 'venue_rental', 'Hallenmiete Februar 2026', 18000, '2026-02-01', $admin->id, $team->id, null],
['expense', 'tournament_fees', 'Hallenmiete Zusatzstunden Turnier', 12000, '2026-02-06', $coach->id, $team->id, 'Ganztages-Hallennutzung'],
['expense', 'training_material','Markierungshütchen Nachbestellung', 1990, '2026-02-20', $coach->id, $team->id, null],
];
foreach ($entries as [$type, $category, $title, $amount, $date, $createdBy, $teamId, $notes]) {
Finance::firstOrCreate(
['title' => $title, 'date' => $date],
[
'team_id' => $teamId,
'type' => $type,
'category' => $category,
'amount' => $amount,
'notes' => $notes,
'created_by' => $createdBy,
]
);
}
}
} }