seed([RoleSeeder::class, SamplePsgcSeeder::class, SampleDropOffPointsSeeder::class]); $this->admin = User::factory()->create(['role' => User::ROLE_ADMIN, 'status' => 'active']); } public function test_aggregator_rolls_up_collection_logs_into_daily_stats(): void { $dop = DropOffPoint::first(); $household = Household::factory()->create(['barangay_id' => $dop->barangay_id]); $batch = app(BatchGenerator::class)->generate(3, QrCodeBatch::PURPOSE_FREE); $batch->codes->each(function ($c) use ($household, $dop) { $c->forceFill([ 'assigned_to_household_id' => $household->id, 'status' => 'used', 'used_at' => now(), 'used_at_drop_off_id' => $dop->id, ])->save(); CollectionLog::create([ 'qr_code_id' => $c->id, 'household_id' => $household->id, 'drop_off_point_id' => $dop->id, 'scanned_at' => now(), 'coordinates_at_scan' => new Point(14.6539, 121.0685, 4326), 'weight_kg' => 5, 'verification_status' => 'valid', ]); }); $count = app(Aggregator::class)->rebuildDailyCollectionStats(now()); $this->assertGreaterThanOrEqual(1, $count); Sanctum::actingAs($this->admin); $response = $this->getJson('/api/v1/admin/reports/daily-collection?from='.now()->toDateString().'&to='.now()->toDateString()); $response->assertOk() ->assertJsonPath('data.totals.total_scans', 3) ->assertJsonPath('data.totals.total_weight_kg', 15); } public function test_admin_can_rebuild_aggregations(): void { Sanctum::actingAs($this->admin); $response = $this->postJson('/api/v1/admin/reports/rebuild', ['date' => now()->toDateString()]); $response->assertOk() ->assertJsonStructure(['data' => ['daily_buckets', 'weekly_buckets', 'monthly_buckets']]); } public function test_compliance_csv_streams_dumpsite_releases(): void { Sanctum::actingAs($this->admin); $response = $this->get('/api/v1/admin/reports/compliance.csv?from=2026-01-01&to=2026-12-31'); $response->assertOk(); $this->assertStringContainsString('text/csv', $response->headers->get('content-type')); $this->assertStringContainsString('released_at,trip_number,dumpsite,permit_number', $response->streamedContent()); } public function test_resident_blocked_from_reports(): void { $resident = User::factory()->create(['role' => User::ROLE_RESIDENT, 'status' => 'active']); Sanctum::actingAs($resident); $this->getJson('/api/v1/admin/reports/daily-collection')->assertStatus(403); } }