create(); $user = User::factory()->create(['tenant_id' => $tenant->id]); $project = Project::factory()->for($tenant)->create([ 'is_active' => true, 'preflight_blocked_at' => now(), 'regions' => [77], ]); $this->actingAs($user)->patchJson("/api/projects/{$project->id}", [ 'regions' => [78], ])->assertOk(); Queue::assertNotPushed(SyncSupplierProjectJob::class); }); it('syncs unblocked project to supplier on update', function () { $tenant = Tenant::factory()->create(); $user = User::factory()->create(['tenant_id' => $tenant->id]); $project = Project::factory()->for($tenant)->create([ 'is_active' => true, 'preflight_blocked_at' => null, 'regions' => [77], ]); $this->actingAs($user)->patchJson("/api/projects/{$project->id}", [ 'regions' => [78], ])->assertOk(); Queue::assertPushed(SyncSupplierProjectJob::class); }); // --- toggle-active (возобновление) --- it('does not launch or sync project on resume when balance insufficient', function () { // Тариф: 50₽/лид. Баланс 100₽ → capacity 2; daily_limit_target=30 → 409. PricingTier::create([ 'tier_no' => 1, 'leads_in_tier' => null, 'price_per_lead_kopecks' => 5000, 'is_active' => true, 'effective_from' => now(), ]); $tenant = Tenant::factory()->create(['balance_rub' => '100.00', 'delivered_in_month' => 0]); $user = User::factory()->create(['tenant_id' => $tenant->id]); $project = Project::factory()->for($tenant)->create([ 'is_active' => false, 'daily_limit_target' => 30, 'preflight_blocked_at' => now(), ]); $this->actingAs($user)->patchJson("/api/projects/{$project->id}/toggle-active", [ 'is_active' => true, ])->assertStatus(409)->assertJsonPath('error', 'balance_insufficient'); Queue::assertNotPushed(SyncSupplierProjectJob::class); expect((bool) $project->fresh()->is_active)->toBeFalse(); }); it('syncs unblocked project to supplier on toggle-active resume', function () { $tenant = Tenant::factory()->create(); $user = User::factory()->create(['tenant_id' => $tenant->id]); $project = Project::factory()->for($tenant)->create([ 'is_active' => false, 'preflight_blocked_at' => null, ]); $this->actingAs($user)->patchJson("/api/projects/{$project->id}/toggle-active", [ 'is_active' => true, ])->assertOk(); Queue::assertPushed(SyncSupplierProjectJob::class); }); // --- ручная «Синхронизировать» (triggerSync) --- it('does not sync blocked project to supplier on manual sync', function () { $tenant = Tenant::factory()->create(); $user = User::factory()->create(['tenant_id' => $tenant->id]); $project = Project::factory()->for($tenant)->create([ 'is_active' => true, 'preflight_blocked_at' => now(), ]); $this->actingAs($user)->postJson("/api/projects/{$project->id}/sync")->assertStatus(202); Queue::assertNotPushed(SyncSupplierProjectJob::class); }); it('syncs unblocked project to supplier on manual sync', function () { $tenant = Tenant::factory()->create(); $user = User::factory()->create(['tenant_id' => $tenant->id]); $project = Project::factory()->for($tenant)->create([ 'is_active' => true, 'preflight_blocked_at' => null, ]); $this->actingAs($user)->postJson("/api/projects/{$project->id}/sync")->assertStatus(202); Queue::assertPushed(SyncSupplierProjectJob::class); });