feat: scale development seeder to 3 LGUs and 10x staff/residents per requested scenario
This commit is contained in:
@@ -8,8 +8,10 @@ use App\Models\DriverProfile;
|
||||
use App\Models\DropOffPoint;
|
||||
use App\Models\Dumpsite;
|
||||
use App\Models\HelperProfile;
|
||||
use App\Models\Household;
|
||||
use App\Models\NotificationPreference;
|
||||
use App\Models\PartnerStore;
|
||||
use App\Models\ResidentProfile;
|
||||
use App\Models\Route as CollectionRoute;
|
||||
use App\Models\RouteStop;
|
||||
use App\Models\ScannerProfile;
|
||||
@@ -34,8 +36,8 @@ class DevelopmentSeeder extends Seeder
|
||||
{
|
||||
$password = Hash::make('password1');
|
||||
|
||||
// 0. Super Admin (Global / Tenant-less)
|
||||
$super = User::firstOrCreate(
|
||||
// 1. Exactly 1 Super Admin
|
||||
User::firstOrCreate(
|
||||
['email' => 'super@verde.local'],
|
||||
[
|
||||
'phone' => '+639000000000',
|
||||
@@ -47,12 +49,13 @@ class DevelopmentSeeder extends Seeder
|
||||
'tenant_id' => null,
|
||||
'email_verified_at' => now(),
|
||||
]
|
||||
);
|
||||
$super->syncRoles(['super_admin']);
|
||||
)->syncRoles(['super_admin']);
|
||||
|
||||
// 2. Three LGUs (Tenants)
|
||||
$lguConfigs = [
|
||||
['code' => 'SPB', 'name' => 'San Pascual, Batangas'],
|
||||
['code' => 'BAU', 'name' => 'Bauan, Batangas'],
|
||||
['code' => 'LEM', 'name' => 'Lemery, Batangas'],
|
||||
];
|
||||
|
||||
foreach ($lguConfigs as $index => $config) {
|
||||
@@ -73,139 +76,62 @@ class DevelopmentSeeder extends Seeder
|
||||
|
||||
private function seedTenantData(Tenant $tenant, string $password, int $lguIndex): void
|
||||
{
|
||||
// 1. Multiple Admins
|
||||
for ($i = 1; $i <= 2; $i++) {
|
||||
$admin = User::firstOrCreate(
|
||||
['email' => "admin{$i}.{$tenant->code}@verde.local"],
|
||||
[
|
||||
'phone' => "+63900{$lguIndex}00000{$i}",
|
||||
'password' => $password,
|
||||
'first_name' => "Verde",
|
||||
'last_name' => "Admin {$i} ({$tenant->code})",
|
||||
'role' => User::ROLE_ADMIN,
|
||||
'status' => User::STATUS_ACTIVE,
|
||||
'tenant_id' => $tenant->id,
|
||||
'email_verified_at' => now(),
|
||||
]
|
||||
);
|
||||
$admin->syncRoles([User::ROLE_ADMIN]);
|
||||
}
|
||||
// NO LGU Admin seeded as requested
|
||||
|
||||
// 2. Geography
|
||||
// 1. Infrastructure (3 Dumpsites, 5 DOPs)
|
||||
$barangay = Barangay::where('name', 'like', '%Poblacion%')->first() ?? Barangay::first();
|
||||
|
||||
$dop = DropOffPoint::firstOrCreate(
|
||||
['name' => "{$tenant->code} Main Plaza"],
|
||||
[
|
||||
$dumpsites = [];
|
||||
for ($i = 1; $i <= 3; $i++) {
|
||||
$dumpsites[] = Dumpsite::create([
|
||||
'name' => "{$tenant->code} Landfill {$i}",
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'code' => "DOP-{$tenant->code}-001",
|
||||
'barangay_id' => $barangay->id,
|
||||
'address_line' => 'City Center',
|
||||
'coordinates' => new Point(14.65 + ($lguIndex * 0.1), 121.06, 4326),
|
||||
]
|
||||
);
|
||||
|
||||
$dumpsite = Dumpsite::firstOrCreate(
|
||||
['name' => "{$tenant->code} Sanitary Landfill"],
|
||||
[
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'code' => "DS-{$tenant->code}-001",
|
||||
'address_line' => 'Waste Management Zone',
|
||||
'coordinates' => new Point(14.67 + ($lguIndex * 0.1), 121.08, 4326),
|
||||
]
|
||||
);
|
||||
|
||||
// 3. Operational Staff (2 Drivers, 2 Helpers, 2 Scanners)
|
||||
for ($i = 1; $i <= 2; $i++) {
|
||||
$driver = $this->createStaff("driver{$i}.{$tenant->code}@verde.local", "+63918{$lguIndex}00000{$i}", "Driver", "{$i}", User::ROLE_DRIVER, $tenant, $password);
|
||||
DriverProfile::updateOrCreate(['user_id' => $driver->id], ['license_number' => "L-{$tenant->code}-{$i}", 'verification_status' => 'approved', 'verified_at' => now()]);
|
||||
|
||||
$helper = $this->createStaff("helper{$i}.{$tenant->code}@verde.local", "+63919{$lguIndex}00000{$i}", "Helper", "{$i}", User::ROLE_HELPER, $tenant, $password);
|
||||
HelperProfile::updateOrCreate(['user_id' => $helper->id], ['verification_status' => 'approved', 'verified_at' => now()]);
|
||||
|
||||
$scanner = $this->createStaff("scanner{$i}.{$tenant->code}@verde.local", "+63920{$lguIndex}00000{$i}", "Scanner", "{$i}", User::ROLE_SCANNER, $tenant, $password);
|
||||
ScannerProfile::updateOrCreate(['user_id' => $scanner->id], ['verification_status' => 'approved', 'verified_at' => now()]);
|
||||
|
||||
// 4. Assets & Teams
|
||||
$truck = Truck::create([
|
||||
'plate_number' => "VRD-{$tenant->code}-{$i}",
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'model' => 'Isuzu Elf',
|
||||
'capacity_kg' => 3000,
|
||||
'status' => Truck::STATUS_ACTIVE,
|
||||
'code' => "DS-{$tenant->code}-00{$i}",
|
||||
'address_line' => "Zone {$i}",
|
||||
'coordinates' => new Point(14.67 + ($i * 0.01), 121.08, 4326),
|
||||
]);
|
||||
|
||||
$team = CollectionTeam::create([
|
||||
'name' => "{$tenant->code} Crew {$i}",
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'driver_id' => $driver->id,
|
||||
'scanner_id' => $scanner->id,
|
||||
'truck_id' => $truck->id,
|
||||
'status' => CollectionTeam::STATUS_ACTIVE,
|
||||
]);
|
||||
TeamMember::create(['team_id' => $team->id, 'user_id' => $helper->id, 'role_in_team' => 'helper', 'assigned_from' => now()]);
|
||||
|
||||
// 5. Routes & Dynamic Trips
|
||||
$route = CollectionRoute::create([
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'code' => "RT-{$tenant->code}-{$i}",
|
||||
'name' => "{$tenant->code} Route {$i}",
|
||||
'default_dumpsite_id' => $dumpsite->id,
|
||||
'default_team_id' => $team->id,
|
||||
'status' => CollectionRoute::STATUS_ACTIVE,
|
||||
]);
|
||||
RouteStop::create(['route_id' => $route->id, 'drop_off_point_id' => $dop->id, 'sequence' => 1, 'estimated_duration_at_stop_minutes' => 15]);
|
||||
|
||||
// Seed Trips for different time periods
|
||||
$tripScenarios = [
|
||||
['date' => now(), 'status' => Trip::STATUS_IN_PROGRESS, 'label' => 'Today'],
|
||||
['date' => now()->subDay(), 'status' => Trip::STATUS_COMPLETED, 'label' => 'Yesterday'],
|
||||
['date' => now()->subMonth(), 'status' => Trip::STATUS_COMPLETED, 'label' => 'Last Month'],
|
||||
['date' => now()->subMonths(2), 'status' => Trip::STATUS_COMPLETED, 'label' => 'Historical'],
|
||||
];
|
||||
|
||||
foreach ($tripScenarios as $scenario) {
|
||||
$tripDate = $scenario['date'];
|
||||
$isCompleted = $scenario['status'] === Trip::STATUS_COMPLETED;
|
||||
|
||||
$trip = Trip::create([
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'trip_number' => "TRIP-{$tenant->code}-{$i}-" . $tripDate->format('Ymd'),
|
||||
'route_id' => $route->id,
|
||||
'team_id' => $team->id,
|
||||
'truck_id' => $truck->id,
|
||||
'dumpsite_id' => $dumpsite->id,
|
||||
'scheduled_date' => $tripDate->format('Y-m-d'),
|
||||
'status' => $scenario['status'],
|
||||
'current_load_kg' => $isCompleted ? rand(1500, 2800) : 0,
|
||||
'actual_start_time' => $isCompleted ? $tripDate->copy()->setHour(8) : ($scenario['label'] === 'Today' ? now()->subHours(2) : null),
|
||||
'actual_end_time' => $isCompleted ? $tripDate->copy()->setHour(14) : null,
|
||||
]);
|
||||
|
||||
TripStop::create([
|
||||
'trip_id' => $trip->id,
|
||||
'drop_off_point_id' => $dop->id,
|
||||
'sequence' => 1,
|
||||
'status' => $isCompleted ? 'completed' : 'pending',
|
||||
'total_scans' => $isCompleted ? rand(50, 100) : 0,
|
||||
'estimated_load_added_kg' => $isCompleted ? rand(500, 800) : 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
// 6. Multiple Stores
|
||||
for ($i = 1; $i <= 2; $i++) {
|
||||
$storeOwner = $this->createStaff("store{$i}.{$tenant->code}@verde.local", "+63921{$lguIndex}00000{$i}", "Store", "Owner {$i}", User::ROLE_STORE_PARTNER, $tenant, $password);
|
||||
StorePartnerProfile::updateOrCreate(['user_id' => $storeOwner->id], ['business_name' => "Store {$i} - {$tenant->code}", 'verification_status' => 'approved', 'verified_at' => now()]);
|
||||
|
||||
$dops = [];
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$dops[] = DropOffPoint::create([
|
||||
'name' => "{$tenant->code} Plaza {$i}",
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'code' => "DOP-{$tenant->code}-00{$i}",
|
||||
'barangay_id' => $barangay->id,
|
||||
'address_line' => "Point {$i}",
|
||||
'coordinates' => new Point(14.65 + ($i * 0.01), 121.06, 4326),
|
||||
]);
|
||||
}
|
||||
|
||||
// 2. Staff & Residents (10 each)
|
||||
$drivers = $this->seedStaff($tenant, $password, $lguIndex, 'driver', 10);
|
||||
$scanners = $this->seedStaff($tenant, $password, $lguIndex, 'scanner', 10);
|
||||
$helpers = $this->seedStaff($tenant, $password, $lguIndex, 'helper', 10);
|
||||
$residents = $this->seedStaff($tenant, $password, $lguIndex, 'resident', 10);
|
||||
|
||||
// 3. Households (10 per LGU)
|
||||
foreach ($residents as $i => $resident) {
|
||||
ResidentProfile::create(['user_id' => $resident->id, 'verification_status' => 'approved', 'verified_at' => now()]);
|
||||
Household::create([
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'name' => "{$resident->last_name} Household",
|
||||
'address_line' => "Street {$i}",
|
||||
'barangay_id' => $barangay->id,
|
||||
'resident_user_id' => $resident->id,
|
||||
'assigned_drop_off_point_id' => $dops[rand(0, 4)]->id,
|
||||
]);
|
||||
}
|
||||
|
||||
// 4. Store Admins (5 per LGU)
|
||||
for ($i = 1; $i <= 5; $i++) {
|
||||
$owner = $this->createStaff("store{$i}.{$tenant->code}@verde.local", "+63921{$lguIndex}000{$i}", "Store", "Owner {$i}", User::ROLE_STORE_PARTNER, $tenant, $password);
|
||||
StorePartnerProfile::create(['user_id' => $owner->id, 'business_name' => "Store {$i} - {$tenant->code}", 'verification_status' => 'approved', 'verified_at' => now()]);
|
||||
$store = PartnerStore::create([
|
||||
'owner_user_id' => $storeOwner->id,
|
||||
'owner_user_id' => $owner->id,
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'business_name' => "Store {$i} - {$tenant->code}",
|
||||
@@ -215,7 +141,101 @@ class DevelopmentSeeder extends Seeder
|
||||
'coordinates' => new Point(14.651 + ($i * 0.001), 121.061, 4326),
|
||||
'status' => PartnerStore::STATUS_ACTIVE,
|
||||
]);
|
||||
StoreInventory::create(['store_id' => $store->id, 'current_code_balance' => 100]);
|
||||
StoreInventory::create(['store_id' => $store->id, 'current_code_balance' => 500]);
|
||||
}
|
||||
|
||||
// 5. Operations (5 Trucks, 5 Teams, 5 Routes, mixed Trips)
|
||||
for ($i = 0; $i < 5; $i++) {
|
||||
$truck = Truck::create([
|
||||
'plate_number' => "VRD-{$tenant->code}-{$i}",
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'capacity_kg' => 3000,
|
||||
'status' => Truck::STATUS_ACTIVE,
|
||||
]);
|
||||
|
||||
$team = CollectionTeam::create([
|
||||
'name' => "{$tenant->code} Team " . ($i + 1),
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'driver_id' => $drivers[$i]->id,
|
||||
'scanner_id' => $scanners[$i]->id,
|
||||
'truck_id' => $truck->id,
|
||||
'status' => CollectionTeam::STATUS_ACTIVE,
|
||||
]);
|
||||
TeamMember::create(['team_id' => $team->id, 'user_id' => $helpers[$i]->id, 'role_in_team' => 'helper', 'assigned_from' => now()]);
|
||||
|
||||
$route = CollectionRoute::create([
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'code' => "RT-{$tenant->code}-{$i}",
|
||||
'name' => "{$tenant->code} Route " . ($i + 1),
|
||||
'default_dumpsite_id' => $dumpsites[rand(0, 2)]->id,
|
||||
'default_team_id' => $team->id,
|
||||
'status' => CollectionRoute::STATUS_ACTIVE,
|
||||
]);
|
||||
RouteStop::create(['route_id' => $route->id, 'drop_off_point_id' => $dops[rand(0, 4)]->id, 'sequence' => 1]);
|
||||
|
||||
$this->seedTrips($tenant, $route, $team, $truck, $dumpsites[rand(0, 2)], $dops);
|
||||
}
|
||||
}
|
||||
|
||||
private function seedStaff($tenant, $password, $lguIndex, $role, $count): array
|
||||
{
|
||||
$users = [];
|
||||
$prefix = [
|
||||
'driver' => '918',
|
||||
'scanner' => '920',
|
||||
'helper' => '919',
|
||||
'resident' => '945'
|
||||
][$role];
|
||||
|
||||
for ($i = 1; $i <= $count; $i++) {
|
||||
$user = $this->createStaff("{$role}{$i}.{$tenant->code}@verde.local", "+63{$prefix}{$lguIndex}000{$i}", ucfirst($role), "{$i} ({$tenant->code})", "{$role}", $tenant, $password);
|
||||
|
||||
if ($role === 'driver') DriverProfile::create(['user_id' => $user->id, 'license_number' => "L-{$tenant->code}-{$i}", 'verification_status' => 'approved', 'verified_at' => now()]);
|
||||
if ($role === 'scanner') ScannerProfile::create(['user_id' => $user->id, 'verification_status' => 'approved', 'verified_at' => now()]);
|
||||
if ($role === 'helper') HelperProfile::create(['user_id' => $user->id, 'verification_status' => 'approved', 'verified_at' => now()]);
|
||||
|
||||
$users[] = $user;
|
||||
}
|
||||
return $users;
|
||||
}
|
||||
|
||||
private function seedTrips($tenant, $route, $team, $truck, $dumpsite, $dops): void
|
||||
{
|
||||
$scenarios = [
|
||||
['date' => now(), 'status' => Trip::STATUS_IN_PROGRESS],
|
||||
['date' => now()->subDay(), 'status' => Trip::STATUS_COMPLETED],
|
||||
['date' => now()->subMonth(), 'status' => Trip::STATUS_COMPLETED],
|
||||
];
|
||||
|
||||
foreach ($scenarios as $scenario) {
|
||||
$isComp = $scenario['status'] === Trip::STATUS_COMPLETED;
|
||||
$trip = Trip::create([
|
||||
'uuid' => (string) Str::uuid(),
|
||||
'tenant_id' => $tenant->id,
|
||||
'trip_number' => "TRIP-{$tenant->code}-" . $scenario['date']->format('YmdHi') . rand(10, 99),
|
||||
'route_id' => $route->id,
|
||||
'team_id' => $team->id,
|
||||
'truck_id' => $truck->id,
|
||||
'dumpsite_id' => $dumpsite->id,
|
||||
'scheduled_date' => $scenario['date']->format('Y-m-d'),
|
||||
'status' => $scenario['status'],
|
||||
'current_load_kg' => $isComp ? rand(1000, 2500) : 0,
|
||||
'actual_start_time' => $scenario['date']->copy()->setHour(8),
|
||||
'actual_end_time' => $isComp ? $scenario['date']->copy()->setHour(12) : null,
|
||||
]);
|
||||
|
||||
foreach ($dops as $idx => $dop) {
|
||||
TripStop::create([
|
||||
'trip_id' => $trip->id,
|
||||
'drop_off_point_id' => $dop->id,
|
||||
'sequence' => $idx + 1,
|
||||
'status' => $isComp ? 'completed' : 'pending',
|
||||
'total_scans' => $isComp ? rand(10, 30) : 0,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -229,7 +249,7 @@ class DevelopmentSeeder extends Seeder
|
||||
'last_name' => $last,
|
||||
'role' => $role,
|
||||
'status' => User::STATUS_ACTIVE,
|
||||
'tenant_id' => $tenant->id,
|
||||
'tenant_id' => $tenant ? $tenant->id : null,
|
||||
'email_verified_at' => now(),
|
||||
]);
|
||||
$u->syncRoles([$role]);
|
||||
|
||||
Reference in New Issue
Block a user