diff --git a/app/app/Jobs/SyncAdAudienceJob.php b/app/app/Jobs/SyncAdAudienceJob.php index 56b23d6c..6f52795c 100644 --- a/app/app/Jobs/SyncAdAudienceJob.php +++ b/app/app/Jobs/SyncAdAudienceJob.php @@ -4,6 +4,7 @@ declare(strict_types=1); namespace App\Jobs; +use App\Models\SalesAdAudienceFirm; use App\Models\SalesAdAudiencePhone; use App\Models\SalesAdAudienceState; use App\Services\Sales\YandexAudienceClient; @@ -44,15 +45,16 @@ class SyncAdAudienceJob implements ShouldQueue return; } - // Номер без фирмы — сирота из старой схемы (до v8.77). Ночной пересчёт обходит - // фирмы, значит такой номер никогда не сменит состояние: попав в сегмент, он - // остался бы в рекламе навсегда. В заливку берём только номера, у которых - // есть хозяин. + // Номер без фирмы — сирота из старой схемы (до v8.77): ночной пересчёт + // обходит фирмы, значит состояние такого номера никогда не сменится и он + // остался бы в сегменте навсегда. Берём только номера с хозяином, и только + // тех хозяев, кого начальник пометил Яндексом (v8.79). /** @var array $phones */ $phones = SalesAdAudiencePhone::query() ->where('state', 'active') ->whereNull('removed_at') ->whereNotNull('firm_id') + ->whereIn('firm_id', SalesAdAudienceFirm::forYandex()->select('id')) ->pluck('phone') ->all(); diff --git a/app/tests/Feature/Sales/AdAudienceSyncTest.php b/app/tests/Feature/Sales/AdAudienceSyncTest.php index 96e1295c..cb70df6b 100644 --- a/app/tests/Feature/Sales/AdAudienceSyncTest.php +++ b/app/tests/Feature/Sales/AdAudienceSyncTest.php @@ -95,3 +95,40 @@ it('ошибку Яндекса показывает начальнику, а н expect(SalesAdAudienceState::current()->last_error)->toContain('quota'); }); + +it('фирму, помеченную только для ВК, в Яндекс не льёт', function () { + // 🔴 Смысл фичи: начальник увёл фирму в ВК — из яндексового сегмента она + // должна уйти сама при ближайшей заливке, без ручной чистки. + config(['services.yandex_audience.token' => 'test-token']); + SalesAdAudienceState::current()->update(['enabled' => true, 'yandex_segment_id' => 58029600]); + + $yandexFirm = SalesAdAudienceFirm::create([ + 'firm_name' => 'Греем в Яндексе', 'warmup_started_at' => now(), 'channels' => 'yandex', + ]); + SalesAdAudiencePhone::create([ + 'phone' => '79990000001', 'firm_id' => $yandexFirm->id, + 'expires_at' => now()->addDays(30), 'state' => 'active', + ]); + + $vkFirm = SalesAdAudienceFirm::create([ + 'firm_name' => 'Греем в ВК', 'warmup_started_at' => now(), 'channels' => 'vk', + ]); + SalesAdAudiencePhone::create([ + 'phone' => '79990000002', 'firm_id' => $vkFirm->id, + 'expires_at' => now()->addDays(30), 'state' => 'active', + ]); + + Http::fake(['api-audience.yandex.ru/*' => Http::response(['result' => true], 200)]); + + SyncAdAudienceJob::dispatchSync(); + + Http::assertSent(function (Illuminate\Http\Client\Request $r) { + $body = collect($r->data())->firstWhere('name', 'file'); + $csv = is_array($body) && is_string($body['contents'] ?? null) ? $body['contents'] : ''; + + expect($csv)->toContain('79990000001') + ->and($csv)->not->toContain('79990000002'); + + return true; + }); +});