feat реклама за показы: ручка Исправить и узкое исключение в замке правки

This commit is contained in:
Дмитрий
2026-07-28 11:43:58 +03:00
parent 729a2636df
commit d29f45da11
4 changed files with 149 additions and 1 deletions
@@ -717,3 +717,87 @@ it('в списке кампаний у отклонённой видна при
expect($res->getContent())->not->toContain('yandex_cost_rub')
->and($res->getContent())->not->toContain('ad_margin_percent');
});
/** Кампания заданного статуса, уже заведённая в Яндексе, со своим пользователем. */
function campaignInYandex(string $status): array
{
$tenant = Tenant::factory()->create();
$user = User::factory()->create(['tenant_id' => $tenant->id]);
$campaign = AdCampaign::create([
'tenant_id' => $tenant->id, 'name' => 'C', 'audience_days' => 10, 'use_uploaded_list' => false,
'status' => $status,
'yandex_campaign_id' => 555, 'yandex_ad_group_id' => 666, 'yandex_segment_id' => 777,
]);
AdCampaignBanner::create([
'tenant_id' => $tenant->id, 'campaign_id' => $campaign->id,
'width' => 300, 'height' => 250, 'bytes' => 1000, 'included' => true,
'path' => 'ad-banners/a/300x250.jpg',
'yandex_creative_id' => 100, 'yandex_ad_id' => 200,
'moderation_status' => AdCampaignBanner::MOD_REJECTED,
]);
return [$tenant, $user, $campaign];
}
it('клиент оживляет свою отклонённую кампанию', function () {
config(['services.yandex_direct.enabled' => false]);
[, $user, $campaign] = campaignInYandex(AdCampaign::STATUS_REJECTED);
$res = $this->actingAs($user)->postJson("/api/advertising/campaigns/{$campaign->id}/revive");
$res->assertOk();
expect($campaign->refresh()->status)->toBe(AdCampaign::STATUS_DRAFT);
});
it('оживить работающую кампанию нельзя', function () {
config(['services.yandex_direct.enabled' => false]);
[, $user, $campaign] = campaignInYandex(AdCampaign::STATUS_RUNNING);
$this->actingAs($user)
->postJson("/api/advertising/campaigns/{$campaign->id}/revive")
->assertStatus(409);
expect($campaign->refresh()->status)->toBe(AdCampaign::STATUS_RUNNING);
});
/**
* Двойной щелчок по «Исправить». Второй заход видит кампанию уже черновиком и обязан
* получить отказ, а не пройти второй раз по чистке номеров: он стёр бы номера объявлений,
* которые к тому моменту мог создать новый запуск.
*/
it('второе нажатие Исправить получает отказ', function () {
config(['services.yandex_direct.enabled' => false]);
[, $user, $campaign] = campaignInYandex(AdCampaign::STATUS_REJECTED);
$this->actingAs($user)->postJson("/api/advertising/campaigns/{$campaign->id}/revive")->assertOk();
$this->actingAs($user)->postJson("/api/advertising/campaigns/{$campaign->id}/revive")->assertStatus(409);
});
it('чужую кампанию оживить нельзя', function () {
config(['services.yandex_direct.enabled' => false]);
[, , $campaignA] = campaignInYandex(AdCampaign::STATUS_REJECTED);
[, $userB] = campaignInYandex(AdCampaign::STATUS_REJECTED);
$this->actingAs($userB)
->postJson("/api/advertising/campaigns/{$campaignA->id}/revive")
->assertStatus(404);
expect($campaignA->refresh()->status)->toBe(AdCampaign::STATUS_REJECTED);
});
it('у отклонённой кампании правка настроек разрешена', function () {
[, $user, $campaign] = campaignInYandex(AdCampaign::STATUS_REJECTED);
$this->actingAs($user)
->patchJson("/api/advertising/campaigns/{$campaign->id}", ['landing_url' => 'https://liderra.ru/new'])
->assertOk();
});
/** 🔑 Исключение не должно протечь на работающую рекламу — она крутится за деньги клиента. */
it('у работающей кампании правка настроек по-прежнему заперта', function () {
[, $user, $campaign] = campaignInYandex(AdCampaign::STATUS_RUNNING);
$this->actingAs($user)
->patchJson("/api/advertising/campaigns/{$campaign->id}", ['landing_url' => 'https://liderra.ru/new'])
->assertStatus(409);
});