This commit is contained in:
Saufi
2026-06-03 08:51:22 +08:00
commit a14d43fe34
347 changed files with 38197 additions and 0 deletions

View File

@@ -0,0 +1,248 @@
<?php
namespace Database\Seeders;
use App\Models\Dun;
use App\Models\Election;
use App\Models\Position;
use App\Models\PositionQuota;
use App\Models\PusatMengundi;
use App\Models\SaluranMengundi;
use App\Models\StaffAssignment;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
class SampleElectionSeeder extends Seeder
{
/**
* Seed sample election hierarchy for development and tests.
*/
public function run(): void
{
$this->cleanupSampleData();
$election = Election::query()->firstOrNew(['code' => 'PRN2026']);
if (! $election->exists) {
$election->public_uuid = (string) Str::uuid();
}
$election->forceFill([
'name' => 'Pilihanraya Negeri 2026',
'status' => 'active',
'starts_at' => now()->toDateString(),
'polling_date' => now()->addWeeks(4)->toDateString(),
])->save();
$election->settings()->updateOrCreate(
['election_id' => $election->id],
[
'registration_start_date' => now()->toDateString(),
'registration_end_date' => now()->addWeeks(3)->toDateString(),
'polling_date' => $election->polling_date,
'is_registration_open' => true,
'is_registration_open_override' => null,
'is_attendance_active' => false,
],
);
$dun = Dun::query()->updateOrCreate(
['election_id' => $election->id, 'code' => 'N49'],
['name' => 'Kota Iskandar'],
);
$pusat = new PusatMengundi;
$pusat->public_uuid = (string) Str::uuid();
$pusat->forceFill([
'election_id' => $election->id,
'code' => 'PM001',
'dun_id' => $dun->id,
'name' => 'SK Seri Contoh',
'address' => 'Jalan Contoh 1, 43000 Kajang, Selangor',
])->save();
$pusat->forceFill([
'registration_url' => url('/pohon/'.$pusat->public_uuid),
])->save();
$this->seedSaluran($election, $pusat);
$this->seedQuotas($election, $pusat);
$this->seedOperationalUsersAndAssignments($election, $pusat);
$pusat->wheelchairAllocation()->updateOrCreate(
['election_id' => $election->id],
[
'allocated_quantity' => 2,
'notes' => 'Sample allocation for Phase 2.',
],
);
}
private function cleanupSampleData(): void
{
$election = Election::query()->where('code', 'PRN2026')->first();
if (! $election) {
return;
}
PositionQuota::query()->where('election_id', $election->id)->forceDelete();
SaluranMengundi::query()->where('election_id', $election->id)->forceDelete();
PusatMengundi::query()->where('election_id', $election->id)->forceDelete();
}
private function seedSaluran(Election $election, PusatMengundi $pusat): void
{
foreach (range(1, 3) as $number) {
$pusat->saluranMengundis()->updateOrCreate(
['number' => (string) $number],
[
'election_id' => $election->id,
'name' => null,
'voter_count' => 450 + ($number * 25),
],
);
}
}
private function seedQuotas(Election $election, PusatMengundi $pusat): void
{
$positions = Position::query()->whereIn('code', [
'PPM',
'PAPM',
'KTM',
'KPDP',
'KP',
'POLIS',
'CALON_TAMBAHAN',
])->get()->keyBy('code');
PositionQuota::query()->updateOrCreate(
[
'election_id' => $election->id,
'pusat_mengundi_id' => $pusat->id,
'saluran_mengundi_id' => null,
'position_id' => $positions['PPM']->id,
],
['quota' => 1],
);
PositionQuota::query()->updateOrCreate(
[
'election_id' => $election->id,
'pusat_mengundi_id' => $pusat->id,
'saluran_mengundi_id' => null,
'position_id' => $positions['PAPM']->id,
],
['quota' => 3],
);
/** @var Collection<int, SaluranMengundi> $salurans */
$salurans = $pusat->saluranMengundis()->get();
foreach ($salurans as $saluran) {
foreach ([
'KTM' => 1,
'KPDP' => 1,
'KP' => 4,
'POLIS' => 1,
'CALON_TAMBAHAN' => 1,
] as $code => $quota) {
PositionQuota::query()->updateOrCreate(
[
'election_id' => $election->id,
'pusat_mengundi_id' => $pusat->id,
'saluran_mengundi_id' => $saluran->id,
'position_id' => $positions[$code]->id,
],
['quota' => $quota],
);
}
}
}
private function seedOperationalUsersAndAssignments(Election $election, PusatMengundi $pusat): void
{
$ppm = $this->seedUser('PPM Contoh', 'ppm@prn.local', ['PPM', 'KTM']);
$ktm = $this->seedUser('KTM Contoh', 'ktm@prn.local', ['KTM']);
$this->seedUser('Admin Kewangan Contoh', 'kewangan@prn.local', ['Admin Kewangan']);
$positions = Position::query()->whereIn('code', ['PPM', 'KTM'])->get()->keyBy('code');
/** @var SaluranMengundi $saluranPertama */
$saluranPertama = $pusat->saluranMengundis()->where('number', '1')->firstOrFail();
/** @var SaluranMengundi $saluranKedua */
$saluranKedua = $pusat->saluranMengundis()->where('number', '2')->firstOrFail();
StaffAssignment::query()->updateOrCreate(
[
'election_id' => $election->id,
'user_id' => $ppm->id,
'position_id' => $positions['PPM']->id,
'pusat_mengundi_id' => $pusat->id,
'saluran_mengundi_id' => null,
],
[
'status' => 'active',
'assigned_at' => now(),
'source' => 'sample_seed',
],
);
StaffAssignment::query()->updateOrCreate(
[
'election_id' => $election->id,
'user_id' => $ppm->id,
'position_id' => $positions['KTM']->id,
'pusat_mengundi_id' => $pusat->id,
'saluran_mengundi_id' => $saluranPertama->id,
],
[
'status' => 'active',
'assigned_at' => now(),
'source' => 'sample_seed_dual_role',
],
);
StaffAssignment::query()->updateOrCreate(
[
'election_id' => $election->id,
'user_id' => $ktm->id,
'position_id' => $positions['KTM']->id,
'pusat_mengundi_id' => $pusat->id,
'saluran_mengundi_id' => $saluranKedua->id,
],
[
'status' => 'active',
'assigned_at' => now(),
'source' => 'sample_seed',
],
);
}
/**
* @param array<int, string> $roles
*/
private function seedUser(string $name, string $email, array $roles): User
{
$user = User::query()->firstOrCreate(
['email' => $email],
[
'name' => $name,
'password' => Hash::make('password'),
'email_verified_at' => now(),
],
);
if ($user->email_verified_at === null) {
$user->forceFill(['email_verified_at' => now()])->save();
}
$user->syncRoles($roles);
return $user;
}
}