Files
portal/app/tests/Feature/Supplier/SyncSupplierProjectJobTest.php
T

158 lines
6.5 KiB
PHP

<?php
declare(strict_types=1);
use App\Jobs\SyncSupplierProjectJob;
use App\Models\Project;
use App\Models\SupplierProject;
use App\Models\Tenant;
use App\Services\Supplier\Channel\SupplierProjectChannel;
use Carbon\Carbon;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Http;
use Tests\Concerns\SharesSupplierPdo;
uses(DatabaseTransactions::class, SharesSupplierPdo::class);
beforeEach(function (): void {
Carbon::setTestNow(Carbon::parse('2026-05-12 10:00:00', 'Europe/Moscow'));
Cache::store('redis')->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);
});