'driver_a@verde.local'], [ 'tenant_id' => $tenantId, 'first_name' => 'Driver', 'last_name' => 'Alpha', 'phone' => '+639111111111', 'password' => $password, 'role' => User::ROLE_DRIVER, 'status' => User::STATUS_ACTIVE, ] ); $scannerA = User::updateOrCreate( ['email' => 'scanner_a@verde.local'], [ 'tenant_id' => $tenantId, 'first_name' => 'Scanner', 'last_name' => 'Alpha', 'phone' => '+639111111112', 'password' => $password, 'role' => User::ROLE_SCANNER, 'status' => User::STATUS_ACTIVE, ] ); $driverB = User::updateOrCreate( ['email' => 'driver_b@verde.local'], [ 'tenant_id' => $tenantId, 'first_name' => 'Driver', 'last_name' => 'Bravo', 'phone' => '+639222222221', 'password' => $password, 'role' => User::ROLE_DRIVER, 'status' => User::STATUS_ACTIVE, ] ); $scannerB = User::updateOrCreate( ['email' => 'scanner_b@verde.local'], [ 'tenant_id' => $tenantId, 'first_name' => 'Scanner', 'last_name' => 'Bravo', 'phone' => '+639222222222', 'password' => $password, 'role' => User::ROLE_SCANNER, 'status' => User::STATUS_ACTIVE, ] ); // 2. Setup Teams $truck = Truck::firstOrCreate( ['plate_number' => 'GEN-001'], [ 'tenant_id' => $tenantId, 'model' => 'Isuzu Elf', 'capacity_kg' => 5000, 'status' => 'active' ] ); $teamA = CollectionTeam::updateOrCreate( ['name' => 'GenSan Team Alpha'], [ 'tenant_id' => $tenantId, 'driver_id' => $driverA->id, 'scanner_id' => $scannerA->id, 'truck_id' => $truck->id, 'status' => CollectionTeam::STATUS_ACTIVE, ] ); $teamB = CollectionTeam::updateOrCreate( ['name' => 'GenSan Team Bravo'], [ 'tenant_id' => $tenantId, 'driver_id' => $driverB->id, 'scanner_id' => $scannerB->id, 'truck_id' => null, // Will assign a truck later or use same 'status' => CollectionTeam::STATUS_ACTIVE, ] ); // 3. Setup Route and Stops $area = ServiceArea::firstOrCreate( ['tenant_id' => $tenantId, 'name' => 'Central District'], [ 'code' => 'GENSAN-CENTRAL', 'status' => 'active' ] ); $route = Route::updateOrCreate( ['name' => 'Morning Central Route'], [ 'tenant_id' => $tenantId, 'area_id' => $area->id, 'code' => 'GENSAN-MORNING-CENTRAL', 'status' => 'active' ] ); // Create 5 Drop Off Points and Route Stops for ($i = 1; $i <= 5; $i++) { $dop = DropOffPoint::firstOrCreate( ['name' => "GenSan Stop $i"], [ 'tenant_id' => $tenantId, 'code' => "GENSAN-STOP-$i", 'address_line' => "GenSan Street Address $i", 'coordinates' => new Point(6.1136 + ($i * 0.001), 125.1719 + ($i * 0.001), 4326), ] ); RouteStop::updateOrCreate( ['route_id' => $route->id, 'drop_off_point_id' => $dop->id], ['sequence' => $i] ); } // 4. Create Trip for Team A $tripA = Trip::updateOrCreate( ['trip_number' => 'TRIP-' . now()->format('Ymd') . '-A1'], [ 'uuid' => Str::uuid(), 'tenant_id' => $tenantId, 'route_id' => $route->id, 'team_id' => $teamA->id, 'truck_id' => $truck->id, 'scheduled_date' => now()->toDateString(), 'scheduled_start_time' => '08:00:00', 'actual_start_time' => now()->subHours(2), 'status' => Trip::STATUS_IN_PROGRESS, 'total_load_kg' => 5000, 'current_load_kg' => 4800, // Almost full ] ); // Copy stops to Trip A foreach ($route->stops as $rs) { TripStop::updateOrCreate( ['trip_id' => $tripA->id, 'sequence' => $rs->sequence], [ 'drop_off_point_id' => $rs->drop_off_point_id, 'status' => $rs->sequence == 1 ? TripStop::STATUS_COMPLETED : TripStop::STATUS_PENDING, 'actual_arrival' => $rs->sequence == 1 ? now()->subHours(1) : null, 'actual_departure' => $rs->sequence == 1 ? now()->subMinutes(45) : null, ] ); } // 5. Simulate 1 QR Scan for Stop 1 $batch = QrCodeBatch::firstOrCreate( ['tenant_id' => $tenantId, 'batch_number' => 'SIM-001'], ['quantity' => 100, 'purpose' => QrCodeBatch::PURPOSE_FREE] ); $qr = QrCode::updateOrCreate( ['serial' => 'VERDE-SIM-001'], [ 'tenant_id' => $tenantId, 'barcode_value' => 'VERDE-SIM-001', 'batch_id' => $batch->id, 'status' => \App\States\QrCode\Active::class, ] ); $household = Household::firstOrCreate( ['tenant_id' => $tenantId, 'address_line' => 'GenSan Main St Simulated'], [ 'head_user_id' => $driverA->id, // Reusing driver as head for sim 'household_size' => 4, 'verification_status' => 'approved' ] ); $qr->update(['assigned_to_household_id' => $household->id]); CollectionLog::updateOrCreate( ['trip_id' => $tripA->id, 'qr_code_id' => $qr->id], [ 'tenant_id' => $tenantId, 'household_id' => $household->id, 'drop_off_point_id' => $route->stops->first()->drop_off_point_id, 'scanned_by_user_id' => $scannerA->id, 'trip_stop_id' => $tripA->stops->first()->id, 'scanned_at' => now()->subHours(1), 'coordinates_at_scan' => new Point(6.1136, 125.1719, 4326), 'weight_kg' => 50, 'waste_type' => 'mixed', 'verification_status' => CollectionLog::STATUS_VALID, ] ); // 6. Assign Team B to continue the route $executor = app(TripExecutor::class); $admin = User::where('role', User::ROLE_ADMIN)->where('tenant_id', $tenantId)->first() ?? User::where('role', User::ROLE_SUPER_ADMIN)->first(); if ($admin) { $executor->createContinuation( originalTrip: $tripA, admin: $admin, newTeamId: $teamB->id, newTruckId: $truck->id, // Use same truck for simulation or different endReason: 'truck_full' ); } $this->command->info('Simulation Seeder Completed Successfully!'); $this->command->info("Team A Trip (Full): {$tripA->trip_number}"); $this->command->info("Team B Account: driver_b@verde.local / password1"); } }