Files
Verde-Web/database/seeders/DemoResidentSeeder.php

128 lines
4.8 KiB
PHP

<?php
namespace Database\Seeders;
use App\Models\Barangay;
use App\Models\Household;
use App\Models\NotificationPreference;
use App\Models\QrCodeBatch;
use App\Models\ResidentProfile;
use App\Models\User;
use App\Services\DropOff\DropOffPointFinder;
use App\Services\Qr\BatchGenerator;
use App\Services\Qr\QrAllocator;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use MatanYadaev\EloquentSpatial\Objects\Point;
/**
* Demo resident accounts for the customer-web walkthrough. Idempotent —
* safe to re-run. Skips QR allocation when a household already has codes.
*
* Logins (all password "password"):
* juan@verde.local → approved household, 10 free codes (full dashboard)
* maria@verde.local → pending household (status banner state)
* pedro@verde.local → no household (lands on onboarding wizard)
*/
class DemoResidentSeeder extends Seeder
{
public function run(QrAllocator $allocator, BatchGenerator $batchGen, DropOffPointFinder $dops): void
{
$barangay = Barangay::first();
if (! $barangay) {
$this->command->warn('No barangay seeded — run SamplePsgcSeeder first.');
return;
}
// Make sure a free QR batch exists so allocateFreeToHousehold has
// codes to hand out. Idempotent — only creates if no free batch.
if (! QrCodeBatch::where('purpose', QrCodeBatch::PURPOSE_FREE)->exists()) {
$batchGen->generate(quantity: 200, purpose: QrCodeBatch::PURPOSE_FREE);
$this->command->info('Generated free QR batch (200 codes).');
}
// Use the barangay centroid as the demo address pin (always inside
// the boundary so geo-resolve and DOP-finder both succeed).
$lat = $barangay->centroid?->latitude ?? 14.6760;
$lng = $barangay->centroid?->longitude ?? 121.0437;
// 1) Juan — approved household + 10 free codes
$juan = $this->createResident('juan@verde.local', '+639170000001', 'Juan', 'Dela Cruz');
$this->createHousehold($juan, $barangay, $lat, $lng, 'approved', $allocator, $dops);
// 2) Maria — pending household
$maria = $this->createResident('maria@verde.local', '+639170000002', 'Maria', 'Santos');
$this->createHousehold($maria, $barangay, $lat + 0.001, $lng + 0.001, 'pending', null, $dops);
// 3) Pedro — no household (tests onboarding flow)
$this->createResident('pedro@verde.local', '+639170000003', 'Pedro', 'Reyes');
$this->command->info('Demo residents seeded:');
$this->command->info(' juan@verde.local → approved + 10 codes');
$this->command->info(' maria@verde.local → pending review');
$this->command->info(' pedro@verde.local → fresh, no household yet');
$this->command->info(' (password for all: "password")');
}
private function createResident(string $email, string $phone, string $first, string $last): User
{
$user = User::firstOrCreate(
['email' => $email],
[
'phone' => $phone,
'password' => Hash::make('password'),
'first_name' => $first,
'last_name' => $last,
'role' => User::ROLE_RESIDENT,
'status' => User::STATUS_ACTIVE,
'email_verified_at' => now(),
'phone_verified_at' => now(),
'preferred_language' => 'en',
],
);
$user->syncRoles([User::ROLE_RESIDENT]);
ResidentProfile::firstOrCreate(['user_id' => $user->id]);
NotificationPreference::firstOrCreate(['user_id' => $user->id]);
return $user;
}
private function createHousehold(
User $head,
Barangay $barangay,
float $lat,
float $lng,
string $status,
?QrAllocator $allocator,
DropOffPointFinder $dops,
): Household {
// Auto-pick the nearest active DOP (matches the production flow
// in HouseholdController::store).
$dop = $dops->nearest($lat, $lng);
$household = Household::firstOrCreate(
['head_user_id' => $head->id],
[
'barangay_id' => $barangay->id,
'address_line' => '123 Demo Street, '.$barangay->name,
'coordinates' => new Point($lat, $lng, 4326),
'household_size' => 4,
'verification_status' => $status,
'verified_at' => $status === 'approved' ? now() : null,
'proof_of_residency_path' => 'demo/proof.jpg',
'assigned_drop_off_point_id' => $dop?->id,
],
);
if ($status === 'approved' && $allocator) {
// Allocator is idempotent — skips when codes already exist.
$allocator->allocateFreeToHousehold($household);
}
return $household;
}
}