Files
portal/app/tests/Feature/Supplier/SupplierRepairProjectNamesCommandTest.php
T

129 lines
5.8 KiB
PHP
Raw Normal View History

<?php
declare(strict_types=1);
use App\Models\SupplierProject;
use Illuminate\Foundation\Testing\DatabaseTransactions;
use Illuminate\Http\Client\Request;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\Http;
use Tests\Concerns\SharesSupplierPdo;
uses(DatabaseTransactions::class, SharesSupplierPdo::class);
/*
* Разовая починка после прод-инцидента 11–12.07.2026: наш ежедневный updateProject слал
* имя без метки канала, и кабинет стирал метку «B<n>_». Строка без метки → лид от неё
* приходит с project без метки → webhook пишет platform=DIRECT вместо B1/B2/B3.
*
* Команда возвращает метку на место. Payload собирается ИЗ ЖИВОЙ СТРОКИ кабинета
* (лимит/дни/регионы/вкл-выкл — как есть), меняется ровно одно поле — name. Регионы
* из кабинета уже в кодах поставщика, повторно их переводить нельзя.
*/
beforeEach(function (): void {
Cache::store('redis')->put('supplier:session', [
'phpsessid' => 'test-session',
'csrf' => 'test-csrf',
], now()->addHour());
config(['services.supplier.portal_url' => 'https://crm.bp-gr.ru']);
});
/** @param array<int, array<string,mixed>> $rows */
function fakeCabinet(array $rows): void
{
Http::fake([
'crm.bp-gr.ru/admin/visit/rt-projects-load*' => Http::response(['projects' => $rows], 200),
'crm.bp-gr.ru/admin/visit/rt-project-save' => Http::response(['status' => 'OK', 'message' => '', 'id' => '1'], 200),
]);
}
/** Строка кабинета с потерянной меткой канала. */
function bareCabinetRow(string $id, string $src, string $content): array
{
return [
'id' => $id, 'src' => $src, 'tag' => 'РФ', 'name' => $content, 'content' => $content,
'type' => 'calls', 'lim' => '5', 'status' => true, 'workdays' => ['1', '2', '3', '4', '5'],
'regions' => '24;66', 'regions_reverse' => false,
];
}
it('dry-run: показывает строки с потерянной меткой, но НИЧЕГО не пишет в кабинет', function (): void {
SupplierProject::factory()->create([
'platform' => 'B1', 'signal_type' => 'call', 'unique_key' => '79135397707',
'supplier_external_id' => '6001', 'inactive_since' => null,
]);
fakeCabinet([bareCabinetRow('6001', 'rt', '79135397707')]);
$this->artisan('supplier:repair-project-names')
->expectsOutputToContain('B1_79135397707')
->assertExitCode(0);
Http::assertNotSent(fn (Request $r): bool => str_contains($r->url(), 'rt-project-save'));
});
it('--apply: возвращает метку канала, сохраняя лимит/дни/регионы/вкл-выкл как есть', function (): void {
SupplierProject::factory()->create([
'platform' => 'B2', 'signal_type' => 'call', 'unique_key' => '79135397707',
'supplier_external_id' => '6002', 'inactive_since' => null,
]);
fakeCabinet([bareCabinetRow('6002', 'bl', '79135397707')]);
$this->artisan('supplier:repair-project-names', ['--apply' => true])->assertExitCode(0);
Http::assertSent(function (Request $r): bool {
if (! str_contains($r->url(), 'rt-project-save')) {
return false;
}
return $r['id'] === 6002
&& $r['name'] === 'B2_79135397707'
&& $r['content'] === '79135397707'
&& $r['srcbl'] === true && $r['srcrt'] === false && $r['srcmt'] === false
&& $r['limit'] === 5
&& $r['status'] === true
&& $r['workdays'] === ['1', '2', '3', '4', '5']
// Регионы из кабинета — уже коды поставщика, отдаём обратно без перевода.
&& $r['regions'] === [24, 66];
});
});
it('не трогает строки, у которых метка на месте, и чужие строки кабинета', function (): void {
SupplierProject::factory()->create([
'platform' => 'B1', 'signal_type' => 'call', 'unique_key' => '79135397707',
'supplier_external_id' => '6003', 'inactive_since' => null,
]);
$withPrefix = bareCabinetRow('6003', 'rt', '79135397707');
$withPrefix['name'] = 'B1_79135397707';
$foreign = bareCabinetRow('9999', 'rt', 'chужой.ru'); // не наш external_id
fakeCabinet([$withPrefix, $foreign]);
$this->artisan('supplier:repair-project-names', ['--apply' => true])->assertExitCode(0);
Http::assertNotSent(fn (Request $r): bool => str_contains($r->url(), 'rt-project-save'));
});
it('--only-active: чинит только включённые у нас строки (выключенные лидов не носят)', function (): void {
SupplierProject::factory()->create([
'platform' => 'B1', 'signal_type' => 'call', 'unique_key' => '79135397707',
'supplier_external_id' => '6004', 'inactive_since' => null,
]);
SupplierProject::factory()->create([
'platform' => 'B3', 'signal_type' => 'call', 'unique_key' => '79990001122',
'supplier_external_id' => '6005', 'inactive_since' => now(),
]);
fakeCabinet([
bareCabinetRow('6004', 'rt', '79135397707'),
bareCabinetRow('6005', 'mt', '79990001122'),
]);
$this->artisan('supplier:repair-project-names', ['--apply' => true, '--only-active' => true])
->assertExitCode(0);
Http::assertSent(fn (Request $r): bool => str_contains($r->url(), 'rt-project-save') && $r['id'] === 6004);
Http::assertNotSent(fn (Request $r): bool => str_contains($r->url(), 'rt-project-save') && $r['id'] === 6005);
});