2026-07-21 15:53:10 +03:00
|
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
|
|
use App\Models\SalesAdAudienceFirm;
|
|
|
|
|
|
use App\Models\SalesAdAudiencePhone;
|
2026-07-22 11:27:09 +03:00
|
|
|
|
use App\Models\SalesAdAudiencePlatform;
|
2026-07-21 15:53:10 +03:00
|
|
|
|
use App\Models\SalesProspect;
|
|
|
|
|
|
use App\Models\SalesUser;
|
|
|
|
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
2026-07-21 16:07:20 +03:00
|
|
|
|
use Illuminate\Support\Facades\DB;
|
2026-07-21 15:53:10 +03:00
|
|
|
|
use Tests\Concerns\SharesSupplierPdo;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* Task 1 плана «кусок B»: firmRow() отдаёт нишу, дату запуска прогрева,
|
|
|
|
|
|
* менеджера (id + имя) и «состояние прогрева» (активен ли прогрев + список
|
|
|
|
|
|
* каналов, на которые фирма реально подписана) — для витрины на вкладках
|
|
|
|
|
|
* площадок. Аутентификация и создание сущностей — как в AdAudiencePlatformApiTest.
|
|
|
|
|
|
*
|
|
|
|
|
|
* SharesSupplierPdo обязателен: SalesAdAudienceFirm/Phone прибиты к
|
|
|
|
|
|
* pgsql_supplier (свой PDO), без шаринга DatabaseTransactions откатывал бы
|
|
|
|
|
|
* только default-соединение (SalesProspect/SalesUser) — записи текли бы
|
|
|
|
|
|
* из теста в тест.
|
|
|
|
|
|
*
|
|
|
|
|
|
* План: docs/superpowers/plans/... (кусок B, Task 1).
|
|
|
|
|
|
*/
|
|
|
|
|
|
uses(DatabaseTransactions::class, SharesSupplierPdo::class);
|
|
|
|
|
|
|
|
|
|
|
|
function warmingFieldsHead(): SalesUser
|
|
|
|
|
|
{
|
|
|
|
|
|
return SalesUser::create([
|
|
|
|
|
|
'name' => 'Начальник '.uniqid(),
|
|
|
|
|
|
'email' => 'wfhead'.uniqid().'@sales.local',
|
|
|
|
|
|
'password' => bcrypt('secret'),
|
|
|
|
|
|
'role' => 'head',
|
|
|
|
|
|
'is_active' => true,
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
function warmingFieldsManager(string $name): SalesUser
|
|
|
|
|
|
{
|
|
|
|
|
|
return SalesUser::create([
|
|
|
|
|
|
'name' => $name,
|
|
|
|
|
|
'email' => 'wfmgr'.uniqid().'@sales.local',
|
|
|
|
|
|
'password' => bcrypt('secret'),
|
|
|
|
|
|
'role' => 'manager',
|
|
|
|
|
|
'is_active' => true,
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
it('firmRow отдаёт нишу, дату запуска, менеджера и состояние прогрева', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
$manager = warmingFieldsManager('Таня Михалева');
|
|
|
|
|
|
|
|
|
|
|
|
$prospect = SalesProspect::create([
|
|
|
|
|
|
'sales_user_id' => $manager->id,
|
|
|
|
|
|
'assigned_by' => $head->id,
|
|
|
|
|
|
'stage' => 'new',
|
|
|
|
|
|
'source' => 'search',
|
|
|
|
|
|
'firm_name' => 'Гарант',
|
|
|
|
|
|
'city' => 'Екатеринбург',
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$firm = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_inn' => '6678048177',
|
|
|
|
|
|
'firm_name' => 'Гарант',
|
|
|
|
|
|
'city' => 'Екатеринбург',
|
|
|
|
|
|
'rubric' => 'Частные стоматологии',
|
|
|
|
|
|
'warmup_started_at' => now()->subDays(4),
|
|
|
|
|
|
'ch_yandex' => true,
|
|
|
|
|
|
'ch_vk' => false,
|
|
|
|
|
|
'ch_mts' => true,
|
|
|
|
|
|
'prospect_id' => $prospect->id,
|
|
|
|
|
|
'assigned_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
2026-07-22 17:38:15 +03:00
|
|
|
|
// Task 8: warming_active/state считаются по строке канала firm_channels(yandex, warming).
|
|
|
|
|
|
// Task C1: warming_channels-бейджи тоже по строкам firm_channels, а не по ch_*.
|
2026-07-22 16:08:35 +03:00
|
|
|
|
$firm->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'yandex', 'status' => 'warming', 'mode' => 'funnel',
|
|
|
|
|
|
'warming_started_at' => $firm->warmup_started_at, 'warmed_times' => 1,
|
|
|
|
|
|
]);
|
2026-07-22 17:38:15 +03:00
|
|
|
|
$firm->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'mts', 'status' => 'loaded', 'mode' => 'funnel',
|
|
|
|
|
|
'warming_started_at' => $firm->warmup_started_at, 'warmed_times' => 0,
|
|
|
|
|
|
]);
|
2026-07-22 16:08:35 +03:00
|
|
|
|
|
2026-07-21 15:53:10 +03:00
|
|
|
|
SalesAdAudiencePhone::create([
|
|
|
|
|
|
'phone' => '79000000001',
|
|
|
|
|
|
'firm_id' => $firm->id,
|
|
|
|
|
|
'firm_inn' => '6678048177',
|
|
|
|
|
|
'state' => 'active',
|
|
|
|
|
|
'expires_at' => now()->addDays(10),
|
|
|
|
|
|
'added_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$row = $this->actingAs($head, 'sales')
|
|
|
|
|
|
->getJson('/api/sales/warming/yandex/firms')
|
|
|
|
|
|
->assertOk()
|
|
|
|
|
|
->json('firms.0');
|
|
|
|
|
|
|
|
|
|
|
|
expect($row['rubric'])->toBe('Частные стоматологии');
|
|
|
|
|
|
expect($row['warmup_started_at'])->not->toBeNull();
|
|
|
|
|
|
expect($row['manager_id'])->toBe($manager->id);
|
|
|
|
|
|
expect($row['manager_name'])->toBe('Таня Михалева');
|
|
|
|
|
|
expect($row['warming_active'])->toBeTrue();
|
|
|
|
|
|
expect($row['warming_channels'])->toContain('yandex');
|
|
|
|
|
|
expect($row['warming_channels'])->toContain('mts');
|
|
|
|
|
|
expect($row['warming_channels'])->not->toContain('vk');
|
|
|
|
|
|
});
|
2026-07-21 16:00:36 +03:00
|
|
|
|
|
2026-07-22 17:38:15 +03:00
|
|
|
|
it('warming_channels строит бейджи из строк firm_channels, а не из ch_*', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
$firm = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_name' => 'По строкам', 'warmup_started_at' => now()->subDay(),
|
|
|
|
|
|
'ch_yandex' => false, 'ch_vk' => false, 'ch_mts' => false,
|
|
|
|
|
|
]);
|
|
|
|
|
|
$firm->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'yandex', 'status' => 'warming', 'mode' => 'funnel',
|
|
|
|
|
|
'warming_started_at' => now(), 'warmed_times' => 1,
|
|
|
|
|
|
]);
|
|
|
|
|
|
$firm->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'mts', 'status' => 'loaded', 'mode' => 'funnel',
|
|
|
|
|
|
'warming_started_at' => now(), 'warmed_times' => 0,
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$row = $this->actingAs($head, 'sales')
|
|
|
|
|
|
->getJson('/api/sales/warming/yandex/firms')
|
|
|
|
|
|
->assertOk()
|
|
|
|
|
|
->json('firms.0');
|
|
|
|
|
|
|
|
|
|
|
|
expect($row['warming_channels'])->toContain('yandex')
|
|
|
|
|
|
->and($row['warming_channels'])->toContain('mts')
|
|
|
|
|
|
->and($row['warming_channels'])->not->toContain('vk');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-07-21 16:00:36 +03:00
|
|
|
|
it('назначает менеджера платформо-независимым маршрутом ad-audience', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
$manager = warmingFieldsManager('Игорь Соколов');
|
|
|
|
|
|
|
|
|
|
|
|
$firm = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_inn' => '6679177538',
|
|
|
|
|
|
'firm_name' => 'Винлайт',
|
|
|
|
|
|
'warmup_started_at' => now()->subDay(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$this->actingAs($head, 'sales')
|
|
|
|
|
|
->postJson("/api/sales/ad-audience/firms/{$firm->id}/assign", ['sales_user_id' => $manager->id])
|
|
|
|
|
|
->assertOk()
|
|
|
|
|
|
->assertJsonStructure(['prospect_id']);
|
|
|
|
|
|
|
|
|
|
|
|
$firm->refresh();
|
|
|
|
|
|
expect($firm->prospect_id)->not->toBeNull();
|
|
|
|
|
|
|
|
|
|
|
|
$this->actingAs($head, 'sales')
|
|
|
|
|
|
->postJson("/api/sales/ad-audience/firms/{$firm->id}/assign", ['sales_user_id' => $manager->id])
|
|
|
|
|
|
->assertStatus(422);
|
|
|
|
|
|
});
|
2026-07-21 16:07:20 +03:00
|
|
|
|
|
|
|
|
|
|
it('ставит канал sms, если номер фирмы попал в отправленную рассылку', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
$firm = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_inn' => '6673240656',
|
|
|
|
|
|
'firm_name' => 'Новодент',
|
|
|
|
|
|
'warmup_started_at' => now()->subDay(),
|
|
|
|
|
|
'ch_yandex' => true,
|
|
|
|
|
|
]);
|
2026-07-22 17:38:15 +03:00
|
|
|
|
// Task C1: фирма попадает в firms(yandex) только при наличии строки канала yandex.
|
|
|
|
|
|
$firm->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'yandex', 'status' => 'loaded', 'mode' => 'funnel',
|
|
|
|
|
|
'warming_started_at' => now(), 'warmed_times' => 0,
|
|
|
|
|
|
]);
|
2026-07-21 16:07:20 +03:00
|
|
|
|
SalesAdAudiencePhone::create([
|
|
|
|
|
|
'phone' => '79220216061',
|
|
|
|
|
|
'firm_id' => $firm->id,
|
|
|
|
|
|
'firm_inn' => '6673240656',
|
|
|
|
|
|
'state' => 'active',
|
|
|
|
|
|
'expires_at' => now()->addDays(10),
|
|
|
|
|
|
'added_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$campaignId = DB::connection('pgsql_supplier')->table('sales_sms_campaigns')->insertGetId([
|
|
|
|
|
|
'title' => 'т', 'body' => 'т', 'status' => 'done', 'created_by' => $head->id,
|
|
|
|
|
|
'created_at' => now(), 'updated_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
DB::connection('pgsql_supplier')->table('sales_sms_messages')->insert([
|
|
|
|
|
|
'campaign_id' => $campaignId, 'phone' => '79220216061', 'status' => 'sent',
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$row = $this->actingAs($head, 'sales')->getJson('/api/sales/warming/yandex/firms')->json('firms.0');
|
|
|
|
|
|
expect($row['warming_channels'])->toContain('sms');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('не ставит sms в песочнице (fake_sent)', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
$firm = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_inn' => '6660000000', 'firm_name' => 'Песочница',
|
|
|
|
|
|
'warmup_started_at' => now()->subDay(), 'ch_yandex' => true,
|
|
|
|
|
|
]);
|
2026-07-22 17:38:15 +03:00
|
|
|
|
// Task C1: строка канала yandex нужна, чтобы фирма вошла в firms(yandex).
|
|
|
|
|
|
$firm->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'yandex', 'status' => 'loaded', 'mode' => 'funnel',
|
|
|
|
|
|
'warming_started_at' => now(), 'warmed_times' => 0,
|
|
|
|
|
|
]);
|
2026-07-21 16:07:20 +03:00
|
|
|
|
SalesAdAudiencePhone::create([
|
|
|
|
|
|
'phone' => '79000000099', 'firm_id' => $firm->id, 'firm_inn' => '6660000000',
|
|
|
|
|
|
'state' => 'active', 'expires_at' => now()->addDays(10), 'added_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
$cid = DB::connection('pgsql_supplier')->table('sales_sms_campaigns')->insertGetId([
|
|
|
|
|
|
'title' => 'т', 'body' => 'т', 'status' => 'done', 'created_by' => $head->id,
|
|
|
|
|
|
'created_at' => now(), 'updated_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
DB::connection('pgsql_supplier')->table('sales_sms_messages')->insert([
|
|
|
|
|
|
'campaign_id' => $cid, 'phone' => '79000000099', 'status' => 'fake_sent',
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$row = $this->actingAs($head, 'sales')->getJson('/api/sales/warming/yandex/firms')->json('firms.0');
|
|
|
|
|
|
expect($row['warming_channels'])->not->toContain('sms');
|
|
|
|
|
|
});
|
2026-07-22 11:27:09 +03:00
|
|
|
|
|
2026-07-22 18:16:48 +03:00
|
|
|
|
it('firmRow отдаёт channel_status строки канала: loaded vs warming', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
|
|
|
|
|
|
// Загружена, ждёт запуска (loaded).
|
|
|
|
|
|
$loaded = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_name' => 'Ждёт запуска', 'warmup_started_at' => now()->subDay(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
$loaded->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'yandex', 'status' => 'loaded', 'mode' => 'funnel',
|
|
|
|
|
|
'warming_started_at' => now(), 'warmed_times' => 0,
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$loadedRow = $this->actingAs($head, 'sales')
|
|
|
|
|
|
->getJson('/api/sales/warming/yandex/firms')->assertOk()->json('firms.0');
|
|
|
|
|
|
expect($loadedRow['channel_status'])->toBe('loaded');
|
|
|
|
|
|
|
|
|
|
|
|
// Другая фирма, гретая (warming).
|
|
|
|
|
|
$warming = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_name' => 'Греется', 'warmup_started_at' => now()->subDay(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
$warming->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'vk', 'status' => 'warming', 'mode' => 'funnel',
|
|
|
|
|
|
'warming_started_at' => now(), 'warmed_times' => 1,
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$warmingRow = $this->actingAs($head, 'sales')
|
|
|
|
|
|
->getJson('/api/sales/warming/vk/firms')->assertOk()->json('firms.0');
|
|
|
|
|
|
expect($warmingRow['channel_status'])->toBe('warming');
|
|
|
|
|
|
});
|
|
|
|
|
|
|
2026-07-22 11:27:09 +03:00
|
|
|
|
it('состояние строки считается по срокам ЗАПРОШЕННОЙ площадки', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
|
|
|
|
|
|
// Одна фирма на yandex+vk, прогрев начат 4 дня назад.
|
|
|
|
|
|
// yandex warmup 5 → ещё active; vk warmup 3 → уже погасла.
|
|
|
|
|
|
SalesAdAudiencePlatform::forCode('yandex')->update(['warmup_days' => 5]);
|
|
|
|
|
|
SalesAdAudiencePlatform::forCode('vk')->update(['warmup_days' => 3]);
|
|
|
|
|
|
|
|
|
|
|
|
$firm = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_name' => 'На обеих', 'warmup_started_at' => now()->subDays(4),
|
|
|
|
|
|
'ch_yandex' => true, 'ch_vk' => true,
|
|
|
|
|
|
]);
|
2026-07-22 16:08:35 +03:00
|
|
|
|
// Task 8: строки каналов — точка отсчёта заезда та же, что и warmup_started_at фирмы.
|
|
|
|
|
|
foreach (['yandex', 'vk'] as $ch) {
|
|
|
|
|
|
$firm->firmChannels()->create([
|
|
|
|
|
|
'channel' => $ch, 'status' => 'warming', 'mode' => 'funnel',
|
|
|
|
|
|
'warming_started_at' => $firm->warmup_started_at, 'warmed_times' => 1,
|
|
|
|
|
|
]);
|
|
|
|
|
|
}
|
2026-07-22 11:27:09 +03:00
|
|
|
|
SalesAdAudiencePhone::create([
|
|
|
|
|
|
'phone' => '79000000055', 'firm_id' => $firm->id,
|
|
|
|
|
|
'state' => 'active', 'expires_at' => now()->addDays(10), 'added_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$yandexRow = $this->actingAs($head, 'sales')->getJson('/api/sales/warming/yandex/firms')->json('firms.0');
|
|
|
|
|
|
$vkRow = $this->actingAs($head, 'sales')->getJson('/api/sales/warming/vk/firms')->json('firms.0');
|
|
|
|
|
|
|
|
|
|
|
|
expect($yandexRow['state'])->toBe('active')
|
|
|
|
|
|
->and($yandexRow['warming_active'])->toBeTrue();
|
|
|
|
|
|
expect($vkRow['state'])->toBe('stopped')
|
|
|
|
|
|
->and($vkRow['warming_active'])->toBeFalse();
|
|
|
|
|
|
});
|
2026-07-22 18:28:43 +03:00
|
|
|
|
|
|
|
|
|
|
// Task D1 (Фаза 2 Этап D): эндпоинт /ad-audience/sms-firms — фирмы со строкой
|
|
|
|
|
|
// канала sms (СМС не греется сроками, всегда status='loaded'), плюс поле
|
|
|
|
|
|
// sms_sent_count (число боевых СМС status='sent' по номерам фирмы) — везде,
|
|
|
|
|
|
// где отдаётся firmRow().
|
|
|
|
|
|
|
|
|
|
|
|
it('sms-firms отдаёт только фирмы со строкой канала sms', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
|
|
|
|
|
|
$withSms = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_inn' => '6670000001', 'firm_name' => 'Со смс',
|
|
|
|
|
|
'warmup_started_at' => now()->subDay(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
$withSms->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'sms', 'status' => 'loaded', 'warmed_times' => 0,
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$withoutSms = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_inn' => '6670000002', 'firm_name' => 'Без смс',
|
|
|
|
|
|
'warmup_started_at' => now()->subDay(), 'ch_yandex' => true,
|
|
|
|
|
|
]);
|
|
|
|
|
|
$withoutSms->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'yandex', 'status' => 'loaded', 'warmed_times' => 0,
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$rows = $this->actingAs($head, 'sales')
|
|
|
|
|
|
->getJson('/api/sales/ad-audience/sms-firms')
|
|
|
|
|
|
->assertOk()
|
|
|
|
|
|
->json('firms');
|
|
|
|
|
|
|
|
|
|
|
|
$ids = array_column($rows, 'id');
|
|
|
|
|
|
expect($ids)->toContain($withSms->id);
|
|
|
|
|
|
expect($ids)->not->toContain($withoutSms->id);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('sms-firms отдаёт sms_sent_count — число боевых СМС по номеру фирмы', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
|
|
|
|
|
|
$firm = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_inn' => '6670000003', 'firm_name' => 'Считаем смс',
|
|
|
|
|
|
'warmup_started_at' => now()->subDay(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
$firm->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'sms', 'status' => 'loaded', 'warmed_times' => 0,
|
|
|
|
|
|
]);
|
|
|
|
|
|
SalesAdAudiencePhone::create([
|
|
|
|
|
|
'phone' => '79110000003', 'firm_id' => $firm->id, 'firm_inn' => '6670000003',
|
|
|
|
|
|
'state' => 'active', 'expires_at' => now()->addDays(10), 'added_at' => now(),
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
// Unique-ограничение (campaign_id, phone) — два sent через РАЗНЫЕ рассылки,
|
|
|
|
|
|
// третий (fake_sent, песочница) в счёт не идёт.
|
|
|
|
|
|
$campaignIds = [
|
|
|
|
|
|
DB::connection('pgsql_supplier')->table('sales_sms_campaigns')->insertGetId([
|
|
|
|
|
|
'title' => 'т1', 'body' => 'т', 'status' => 'done', 'created_by' => $head->id,
|
|
|
|
|
|
'created_at' => now(), 'updated_at' => now(),
|
|
|
|
|
|
]),
|
|
|
|
|
|
DB::connection('pgsql_supplier')->table('sales_sms_campaigns')->insertGetId([
|
|
|
|
|
|
'title' => 'т2', 'body' => 'т', 'status' => 'done', 'created_by' => $head->id,
|
|
|
|
|
|
'created_at' => now(), 'updated_at' => now(),
|
|
|
|
|
|
]),
|
|
|
|
|
|
DB::connection('pgsql_supplier')->table('sales_sms_campaigns')->insertGetId([
|
|
|
|
|
|
'title' => 'т3', 'body' => 'т', 'status' => 'done', 'created_by' => $head->id,
|
|
|
|
|
|
'created_at' => now(), 'updated_at' => now(),
|
|
|
|
|
|
]),
|
|
|
|
|
|
];
|
|
|
|
|
|
DB::connection('pgsql_supplier')->table('sales_sms_messages')->insert([
|
|
|
|
|
|
['campaign_id' => $campaignIds[0], 'phone' => '79110000003', 'status' => 'sent'],
|
|
|
|
|
|
['campaign_id' => $campaignIds[1], 'phone' => '79110000003', 'status' => 'sent'],
|
|
|
|
|
|
['campaign_id' => $campaignIds[2], 'phone' => '79110000003', 'status' => 'fake_sent'],
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$row = $this->actingAs($head, 'sales')
|
|
|
|
|
|
->getJson('/api/sales/ad-audience/sms-firms')
|
|
|
|
|
|
->assertOk()
|
|
|
|
|
|
->json('firms.0');
|
|
|
|
|
|
|
|
|
|
|
|
expect($row['sms_sent_count'])->toBe(2);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('sms-firms доступен только начальнику', function () {
|
|
|
|
|
|
$manager = warmingFieldsManager('Обычный менеджер');
|
|
|
|
|
|
|
|
|
|
|
|
$this->actingAs($manager, 'sales')
|
|
|
|
|
|
->getJson('/api/sales/ad-audience/sms-firms')
|
|
|
|
|
|
->assertStatus(403);
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
it('firmRow отдаёт sms_sent_count=0, если СМС не слали', function () {
|
|
|
|
|
|
$head = warmingFieldsHead();
|
|
|
|
|
|
$firm = SalesAdAudienceFirm::create([
|
|
|
|
|
|
'firm_name' => 'Без счёта смс', 'warmup_started_at' => now()->subDay(), 'ch_yandex' => true,
|
|
|
|
|
|
]);
|
|
|
|
|
|
$firm->firmChannels()->create([
|
|
|
|
|
|
'channel' => 'yandex', 'status' => 'loaded', 'warmed_times' => 0,
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
$row = $this->actingAs($head, 'sales')
|
|
|
|
|
|
->getJson('/api/sales/warming/yandex/firms')
|
|
|
|
|
|
->assertOk()
|
|
|
|
|
|
->json('firms.0');
|
|
|
|
|
|
|
|
|
|
|
|
expect($row['sms_sent_count'])->toBe(0);
|
|
|
|
|
|
});
|