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

224 lines
9.6 KiB
PHP

<?php
namespace Database\Seeders;
use App\Models\Barangay;
use App\Models\CollectionTeam;
use App\Models\DriverProfile;
use App\Models\DropOffPoint;
use App\Models\Dumpsite;
use App\Models\HelperProfile;
use App\Models\NotificationPreference;
use App\Models\PartnerStore;
use App\Models\Route as CollectionRoute;
use App\Models\RouteStop;
use App\Models\ScannerProfile;
use App\Models\StoreInventory;
use App\Models\StorePartnerProfile;
use App\Models\TeamMember;
use App\Models\Tenant;
use App\Models\Trip;
use App\Models\TripStop;
use App\Models\Truck;
use App\Models\User;
use App\Tenancy\Tenancy;
use Carbon\Carbon;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use MatanYadaev\EloquentSpatial\Objects\Point;
class DevelopmentSeeder extends Seeder
{
public function run(): void
{
$password = Hash::make('password1');
$lguConfigs = [
['code' => 'SPB', 'name' => 'San Pascual, Batangas'],
['code' => 'BAU', 'name' => 'Bauan, Batangas'],
];
foreach ($lguConfigs as $index => $config) {
$tenant = Tenant::firstOrCreate(
['code' => $config['code']],
[
'name' => $config['name'],
'status' => Tenant::STATUS_ACTIVE,
'qr_retail_price_centavos' => 1000,
'uuid' => (string) Str::uuid(),
]
);
Tenancy::setCurrent($tenant);
$this->seedTenantData($tenant, $password, $index);
}
}
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]);
}
// 2. Geography
$barangay = Barangay::where('name', 'like', '%Poblacion%')->first() ?? Barangay::first();
$dop = DropOffPoint::firstOrCreate(
['name' => "{$tenant->code} Main Plaza"],
[
'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,
]);
$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()]);
$store = PartnerStore::create([
'owner_user_id' => $storeOwner->id,
'uuid' => (string) Str::uuid(),
'tenant_id' => $tenant->id,
'business_name' => "Store {$i} - {$tenant->code}",
'business_permit_number' => "BP-{$tenant->code}-{$i}",
'address_line' => "Market St {$i}",
'barangay_id' => $barangay->id,
'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]);
}
}
private function createStaff($email, $phone, $first, $last, $role, $tenant, $password): User
{
$u = User::create([
'email' => $email,
'phone' => $phone,
'password' => $password,
'first_name' => $first,
'last_name' => $last,
'role' => $role,
'status' => User::STATUS_ACTIVE,
'tenant_id' => $tenant->id,
'email_verified_at' => now(),
]);
$u->syncRoles([$role]);
NotificationPreference::firstOrCreate(['user_id' => $u->id]);
return $u;
}
}