tenant = Tenant::factory()->create(); config(['services.yandex_direct.enabled' => true]); config(['services.yandex_direct.token' => 'DIRTOKEN']); config(['services.yandex_direct.base_url' => 'https://api-sandbox.direct.yandex.com']); }); it('остановка без денег сперва платит за показанное, потом отпускает заморозку', function () { Http::fake([ '*/json/v5/campaigns' => Http::response(['result' => ['SuspendResults' => [['Id' => 777]]]]), '*/json/v5/reports' => Http::response('2500', 200), // накопительно за всё время ]); $svc = app(AdWalletService::class); $svc->topup($this->tenant->id, '3000.00', 'yandex', 'тест'); $campaign = AdCampaign::create([ 'tenant_id' => $this->tenant->id, 'name' => 'Кончились деньги на ходу', 'audience_days' => 10, 'status' => AdCampaign::STATUS_RUNNING, 'yandex_campaign_id' => 777, 'estimated_impressions' => 10000, 'paid_impressions' => 10000, 'charged_client_rub' => '0.00', ]); $svc->freeze($this->tenant->id, 'yandex', 'campaign', $campaign->id, '1200.00'); event(new AdvertisingStopped($this->tenant->id)); $wallet = AdWallet::where('tenant_id', $this->tenant->id)->first(); // 2500 показов × 120 ₽ за тысячу = 300 ₽ — они обязаны уйти с баланса. expect((string) $campaign->fresh()->charged_client_rub)->toBe('300.00') ->and((string) $wallet->balance_rub)->toBe('2700.00') ->and((string) $wallet->frozen_rub)->toBe('0.00') ->and($campaign->fresh()->status)->toBe(AdCampaign::STATUS_STOPPED_NO_FUNDS); }); it('не узнали число показов — рекламу глушим, но деньги НЕ отпускаем', function () { Http::fake([ '*/json/v5/campaigns' => Http::response(['result' => ['SuspendResults' => [['Id' => 778]]]]), '*/json/v5/reports' => Http::response(['error' => ['error_detail' => 'нет доступа']], 400), ]); $svc = app(AdWalletService::class); $svc->topup($this->tenant->id, '3000.00', 'yandex', 'тест'); $campaign = AdCampaign::create([ 'tenant_id' => $this->tenant->id, 'name' => 'Отчёт не отдался', 'audience_days' => 10, 'status' => AdCampaign::STATUS_RUNNING, 'yandex_campaign_id' => 778, 'estimated_impressions' => 10000, 'paid_impressions' => 10000, 'charged_client_rub' => '0.00', ]); $svc->freeze($this->tenant->id, 'yandex', 'campaign', $campaign->id, '1200.00'); event(new AdvertisingStopped($this->tenant->id)); $wallet = AdWallet::where('tenant_id', $this->tenant->id)->first(); // Реклама заглушена — статус сменился. expect($campaign->fresh()->status)->toBe(AdCampaign::STATUS_STOPPED_NO_FUNDS) // Но заморозка на месте: отпустить, не заплатив, значит подарить показы. ->and((string) $wallet->frozen_rub)->toBe('1200.00') ->and((string) $campaign->fresh()->charged_client_rub)->toBe('0.00'); });