Files
portal/app/tests/Feature/Sales/ProspectWarmingBadgeTest.php
T
Дмитрий fc16500fea feat(прогрев): блок warming (active + каналы) в ответе по проспектам
Task 4 плана «три площадки прогрева» кусок B: GET /api/sales/prospects
теперь отдаёт warming.active/warming.channels на каждой карточке —
сопоставление SalesAdAudienceFirm.prospect_id в PHP (pgsql_supplier
против default connection), без cross-connection JOIN. Канал sms —
если номер фирмы попал в отправленную (status=sent) рассылку.
2026-07-21 16:16:41 +03:00

113 lines
4.1 KiB
PHP

<?php
declare(strict_types=1);
use App\Models\SalesAdAudienceFirm;
use App\Models\SalesAdAudiencePhone;
use App\Models\SalesProspect;
use App\Models\SalesUser;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Support\Facades\DB;
use Tests\Concerns\SharesSupplierPdo;
/**
* Task 4 плана «кусок B»: карточка проспекта в ответе GET /api/sales/prospects
* несёт блок `warming` (активен ли прогрев + список каналов), чтобы канбан
* воронки мог показать «греется/прогрет». Фирма (pgsql_supplier) связывается
* с проспектом (default connection) через SalesAdAudienceFirm.prospect_id —
* JOIN между соединениями невозможен, сопоставление в PHP (SalesProspectController::warmingByProspect).
*
* SharesSupplierPdo обязателен — см. AdAudienceWarmingFieldsTest.
*
* План: docs/superpowers/plans/2026-07-21-progrev-4-stranicy-portal.md (кусок B, Task 4).
*/
uses(DatabaseTransactions::class, SharesSupplierPdo::class);
function pwb_manager(): SalesUser
{
return SalesUser::create([
'name' => 'Менеджер '.uniqid(),
'email' => 'pwb'.uniqid().'@sales.local',
'password' => bcrypt('secret'),
'role' => 'manager',
'is_active' => true,
]);
}
it('карточка проспекта несёт состояние прогрева и каналы', function () {
$manager = pwb_manager();
$prospect = SalesProspect::create([
'sales_user_id' => $manager->id,
'stage' => 'new',
'source' => 'search',
'firm_name' => 'Гарант',
]);
$firm = SalesAdAudienceFirm::create([
'firm_inn' => '6678048177',
'firm_name' => 'Гарант',
'warmup_started_at' => now()->subDays(2),
'ch_yandex' => true,
'ch_vk' => true,
'prospect_id' => $prospect->id,
'assigned_at' => now(),
]);
SalesAdAudiencePhone::create([
'phone' => '79000000002',
'firm_id' => $firm->id,
'firm_inn' => '6678048177',
'state' => 'active',
'expires_at' => now()->addDays(5),
'added_at' => now(),
]);
$row = $this->actingAs($manager, 'sales')
->getJson('/api/sales/prospects')
->assertOk()
->json('prospects.0');
expect($row['warming']['active'])->toBeTrue();
expect($row['warming']['channels'])->toContain('yandex');
expect($row['warming']['channels'])->toContain('vk');
});
it('карточка проспекта показывает канал sms, если номер попал в отправленную рассылку', function () {
$manager = pwb_manager();
$prospect = SalesProspect::create([
'sales_user_id' => $manager->id,
'stage' => 'new',
'source' => 'search',
'firm_name' => 'Новодент',
]);
$firm = SalesAdAudienceFirm::create([
'firm_inn' => '6673240656',
'firm_name' => 'Новодент',
'warmup_started_at' => now()->subDay(),
'ch_yandex' => true,
'prospect_id' => $prospect->id,
'assigned_at' => now(),
]);
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' => $manager->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($manager, 'sales')
->getJson('/api/sales/prospects')
->assertOk()
->json('prospects.0');
expect($row['warming']['channels'])->toContain('sms');
});