fix реклама Яндекса: принятые объявления сами уходят в показ — модерация приняла, это ещё не показ
У объявления два независимых признака: вердикт модерации (Status) и идёт ли показ (State). Созданное программой объявление рождается выключенным, и включение кампании его не поднимает — команды поднять сами объявления в коде не было вообще. Живая приёмка 31.07.2026, кампания 713175197: принята и включена, Яндекс на уровне кампании пишет «Идут показы», а внутри все 15 объявлений выключены. Показов ноль при замороженных у клиента 3333.36 руб. Опросчик теперь чинит по СОСТОЯНИЮ из ответа Яндекса, а не по переходу статуса: собирает объявления со статусом «принято» и выключенным показом и зовёт ads.resume. Так самовосстанавливается и уже запущенная кампания — по переходу она осталась бы выключенной навсегда, потому что «принято» у нас записано давно. Состояние Яндекс присылал в каждом ответе и раньше, опросчик его просто выбрасывал. Проверено вырезанием: без починки новый тест краснеет. Реклама 349 из 349.
This commit is contained in:
@@ -522,3 +522,61 @@ it('пока разведка не сходила, заглушка клиент
|
||||
expect($first)->not->toBeNull()
|
||||
->and($first->body)->toContain('причину не назвал');
|
||||
});
|
||||
|
||||
/**
|
||||
* 🔴 Модерация приняла — это ещё НЕ показ. У объявления два независимых признака:
|
||||
* вердикт (Status) и включён ли показ (State). Созданное программой объявление
|
||||
* рождается выключенным, и включение кампании его не поднимает.
|
||||
*
|
||||
* Живая приёмка 31.07.2026: кампания принята и включена, Яндекс пишет «Идут показы»,
|
||||
* а внутри все 15 объявлений выключены — показов ноль при замороженных деньгах клиента.
|
||||
*/
|
||||
it('включает принятые объявления, которые Яндекс держит выключенными', function () {
|
||||
configureYandexForModeration();
|
||||
Http::fake(['*/json/v5/ads' => Http::response(['result' => ['Ads' => [
|
||||
['Id' => 7701, 'State' => 'OFF', 'StatusClarification' => null, 'Status' => 'ACCEPTED'],
|
||||
['Id' => 7702, 'State' => 'OFF', 'StatusClarification' => null, 'Status' => 'ACCEPTED'],
|
||||
]]])]);
|
||||
|
||||
makeModeratedCampaignWithBanners([7701, 7702]);
|
||||
|
||||
(new SyncCampaignModerationJob)->handle();
|
||||
|
||||
Http::assertSent(function ($request) {
|
||||
$data = $request->data();
|
||||
|
||||
return ($data['method'] ?? null) === 'resume'
|
||||
&& ($data['params']['SelectionCriteria']['Ids'] ?? []) === [7701, 7702];
|
||||
});
|
||||
});
|
||||
|
||||
/**
|
||||
* Обратная сторона: лишний раз дёргать Яндекс нельзя. Объявление, которое уже
|
||||
* показывается, включать не за чем — иначе на каждом обходе улетал бы холостой запрос.
|
||||
*/
|
||||
it('не дёргает включение у объявления, которое и так показывается', function () {
|
||||
configureYandexForModeration();
|
||||
Http::fake(['*/json/v5/ads' => Http::response(['result' => ['Ads' => [
|
||||
['Id' => 7703, 'State' => 'ON', 'StatusClarification' => null, 'Status' => 'ACCEPTED'],
|
||||
]]])]);
|
||||
|
||||
makeModeratedCampaignWithBanners([7703]);
|
||||
|
||||
(new SyncCampaignModerationJob)->handle();
|
||||
|
||||
Http::assertNotSent(fn ($request) => ($request->data()['method'] ?? null) === 'resume');
|
||||
});
|
||||
|
||||
/** Отклонённое объявление включать нельзя: показывать его Яндекс всё равно не будет. */
|
||||
it('не включает отклонённое объявление', function () {
|
||||
configureYandexForModeration();
|
||||
Http::fake(['*/json/v5/ads' => Http::response(['result' => ['Ads' => [
|
||||
['Id' => 7704, 'State' => 'OFF', 'StatusClarification' => 'Нельзя', 'Status' => 'REJECTED'],
|
||||
]]])]);
|
||||
|
||||
makeModeratedCampaignWithBanners([7704]);
|
||||
|
||||
(new SyncCampaignModerationJob)->handle();
|
||||
|
||||
Http::assertNotSent(fn ($request) => ($request->data()['method'] ?? null) === 'resume');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user