delete(); DB::table('users')->delete(); DB::table('tenants')->delete(); }); function seedTenant(array $over = []): int { return DB::table('tenants')->insertGetId(array_merge([ 'subdomain' => 'acme'.uniqid(), 'organization_name' => 'Acme', 'contact_email' => 'a@acme.ru', 'status' => 'active', 'is_trial' => false, 'balance_rub' => 100, 'balance_leads' => 0, 'chargeback_unrecovered_rub' => 0, 'delivered_in_month' => 0, 'created_at' => now(), 'updated_at' => now(), ], $over)); } it('GET /api/admin/dashboard/clients возвращает KPI + новых + спящих', function () { // новый клиент, заходил недавно $t1 = seedTenant(['organization_name' => 'Новый Актив', 'created_at' => now()->subDays(2)]); DB::table('users')->insert(['tenant_id' => $t1, 'email' => 'u1@x.ru', 'password_hash' => bcrypt('x'), 'last_login_at' => now()->subDay(), 'created_at' => now(), 'updated_at' => now()]); // новый клиент, НИ РАЗУ не заходил → спящий $t2 = seedTenant(['organization_name' => 'Не Активировался', 'created_at' => now()->subDays(3)]); DB::table('users')->insert(['tenant_id' => $t2, 'email' => 'u2@x.ru', 'password_hash' => bcrypt('x'), 'last_login_at' => null, 'created_at' => now(), 'updated_at' => now()]); $res = $this->getJson('/api/admin/dashboard/clients?period=30d'); $res->assertOk(); $res->assertJsonStructure([ 'kpi' => ['total_active', 'new_count', 'logged_in', 'got_leads', 'paid'], 'new_clients' => [['id', 'organization_name', 'created_at', 'last_login_at', 'delivered_in_month', 'balance_rub', 'status']], 'dormant' => [['id', 'organization_name', 'last_login_at', 'balance_rub']], ]); expect($res->json('kpi.total_active'))->toBe(2); expect($res->json('kpi.new_count'))->toBe(2); expect($res->json('kpi.logged_in'))->toBe(1); // спящий = не активировавшийся t2 expect(collect($res->json('dormant'))->pluck('organization_name'))->toContain('Не Активировался'); }); it('summary включает плитку clients со светофором', function () { $t = seedTenant(['created_at' => now()->subDays(1)]); DB::table('users')->insert(['tenant_id' => $t, 'email' => 'u@x.ru', 'password_hash' => bcrypt('x'), 'last_login_at' => null, 'created_at' => now(), 'updated_at' => now()]); $res = $this->getJson('/api/admin/dashboard?period=30d'); $res->assertOk(); $res->assertJsonStructure(['clients' => ['light', 'total_active', 'new_count', 'logged_in', 'dormant']]); // есть не активировавшийся → светофор amber expect($res->json('clients.light'))->toBe('amber'); });