put('supplier:session', [ 'phpsessid' => 'sess123', 'csrf' => 'csrf123', 'refreshed_at' => now()->toIso8601String(), ], now()->addHours(6)); config(['services.supplier.portal_url' => 'https://crm.bp-gr.ru']); config(['services.supplier.alert_email' => 'ops@liderra.test']); // Default to batch mode so existing Plan5 tests are unaffected DB::table('system_settings')->where('key', 'supplier_export_mode')->update(['value' => 'batch']); }); afterEach(function (): void { Cache::store('redis')->forget('supplier:session'); Carbon::setTestNow(); }); // --------------------------------------------------------------------------- // Online mode: per-subject supplier_projects + pivot // --------------------------------------------------------------------------- it('online mode creates per-subject supplier_projects with full params + pivot', function (): void { DB::table('system_settings')->where('key', 'supplier_export_mode')->update(['value' => 'online']); $tenant = Tenant::factory()->create(['balance_leads' => 100]); $project = Project::factory()->create([ 'tenant_id' => $tenant->id, 'signal_type' => 'site', 'signal_identifier' => 'okna.ru', 'is_active' => true, 'daily_limit_target' => 12, 'regions' => [82], 'delivery_days_mask' => 127, ]); // saveProjectMultiFlag → rt-project-save + listProjects → 3 ids Http::fake([ 'crm.bp-gr.ru/admin/visit/rt-project-save' => Http::response( ['status' => 'OK', 'message' => '', 'result' => null, 'id' => '1001'], 200, ), 'crm.bp-gr.ru/admin/visit/rt-projects-load*' => Http::response( ['projects' => [ ['id' => '1001', 'src' => 'rt', 'name' => 'okna.ru', 'tag' => 'Москва', 'type' => 'hosts', 'content' => 'okna.ru'], ['id' => '1002', 'src' => 'bl', 'name' => 'okna.ru', 'tag' => 'Москва', 'type' => 'hosts', 'content' => 'okna.ru'], ['id' => '1003', 'src' => 'mt', 'name' => 'okna.ru', 'tag' => 'Москва', 'type' => 'hosts', 'content' => 'okna.ru'], ]], 200, ), ]); (new SyncSupplierProjectJob($project->id))->handle(app(SupplierProjectChannel::class)); // 3 supplier_projects: subject_code=82, platforms B1/B2/B3 expect(SupplierProject::where('unique_key', 'okna.ru')->where('subject_code', 82)->count())->toBe(3); // pivot: 3 links for this project expect(DB::table('project_supplier_links')->where('project_id', $project->id)->count())->toBe(3); }); it('online mode all-RF (no regions): 1 group subject_code=null, 3 supplier_projects + 3 pivot links', function (): void { DB::table('system_settings')->where('key', 'supplier_export_mode')->update(['value' => 'online']); $tenant = Tenant::factory()->create(['balance_leads' => 100]); $project = Project::factory()->create([ 'tenant_id' => $tenant->id, 'signal_type' => 'site', 'signal_identifier' => 'allrf.example.com', 'is_active' => true, 'daily_limit_target' => 6, 'regions' => [], 'delivery_days_mask' => 127, ]); Http::fake([ 'crm.bp-gr.ru/admin/visit/rt-project-save' => Http::response( ['status' => 'OK', 'message' => '', 'result' => null, 'id' => '500'], 200, ), 'crm.bp-gr.ru/admin/visit/rt-projects-load*' => Http::response( ['projects' => [ ['id' => '500', 'src' => 'rt', 'name' => 'allrf.example.com', 'tag' => 'РФ', 'type' => 'hosts', 'content' => 'allrf.example.com'], ['id' => '501', 'src' => 'bl', 'name' => 'allrf.example.com', 'tag' => 'РФ', 'type' => 'hosts', 'content' => 'allrf.example.com'], ['id' => '502', 'src' => 'mt', 'name' => 'allrf.example.com', 'tag' => 'РФ', 'type' => 'hosts', 'content' => 'allrf.example.com'], ]], 200, ), ]); (new SyncSupplierProjectJob($project->id))->handle(app(SupplierProjectChannel::class)); $sps = SupplierProject::where('unique_key', 'allrf.example.com')->get(); expect($sps)->toHaveCount(3); expect($sps->pluck('subject_code')->unique()->all())->toContain(null); expect(DB::table('project_supplier_links')->where('project_id', $project->id)->count())->toBe(3); }); // --------------------------------------------------------------------------- // Batch mode: keeps каркас (limit 0, no per-subject save, no pivot) // --------------------------------------------------------------------------- it('batch mode keeps каркас (limit=0, sets supplier_b{1,2,3}_project_id, no project_supplier_links pivot)', function (): void { // batch is already set in beforeEach — no change needed $tenant = Tenant::factory()->create(); $project = Project::factory()->create([ 'tenant_id' => $tenant->id, 'signal_type' => 'site', 'signal_identifier' => 'batch-test.ru', 'is_active' => true, 'daily_limit_target' => 10, 'regions' => [82], 'delivery_days_mask' => 127, ]); $this->mock(SupplierProjectChannel::class, function ($mock): void { $mock->shouldReceive('createProject')->times(3)->andReturn(200001, 200002, 200003); }); (new SyncSupplierProjectJob($project->id))->handle(app(SupplierProjectChannel::class)); $project->refresh(); // Batch: the old FK columns are set expect($project->supplier_b1_project_id)->not->toBeNull(); expect($project->supplier_b2_project_id)->not->toBeNull(); expect($project->supplier_b3_project_id)->not->toBeNull(); // Batch: каркас → limit=0 $sp = SupplierProject::find($project->supplier_b1_project_id); expect($sp->current_limit)->toBe(0); // Batch: no pivot rows (nightly job fills them) expect(DB::table('project_supplier_links')->where('project_id', $project->id)->count())->toBe(0); });