2026-07-23 12:28:58 +03:00
|
|
|
<?php
|
|
|
|
|
|
|
|
|
|
declare(strict_types=1);
|
|
|
|
|
|
|
|
|
|
use App\Models\SalesAdAudiencePhone;
|
2026-07-23 12:34:02 +03:00
|
|
|
use App\Models\SalesSmsMessage;
|
2026-07-23 12:28:58 +03:00
|
|
|
use App\Services\Sms\OperatorNormalizer;
|
|
|
|
|
use App\Services\Sms\Providers\MtsSmsProvider;
|
|
|
|
|
use App\Services\Sms\Providers\SmscSmsProvider;
|
|
|
|
|
use App\Services\Sms\SmsRecipientSelector;
|
|
|
|
|
use App\Services\Sms\SmsRouter;
|
|
|
|
|
use Illuminate\Foundation\Testing\DatabaseTransactions;
|
|
|
|
|
use Tests\Concerns\SharesSupplierPdo;
|
|
|
|
|
|
|
|
|
|
uses(DatabaseTransactions::class, SharesSupplierPdo::class);
|
|
|
|
|
|
2026-07-23 12:34:02 +03:00
|
|
|
/** Роутер ТОЛЬКО с каналом МТС — без универсала. Так нормализация становится
|
|
|
|
|
* нагруженной: сырое «ПАО "МТС"» пройдёт только если его привели к ключу 'mts'. */
|
|
|
|
|
function mts_only_router(): SmsRouter
|
|
|
|
|
{
|
|
|
|
|
return new SmsRouter([new MtsSmsProvider('t', ['mts'], ['*' => 400])]);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
function two_channel_router(): SmsRouter
|
2026-07-23 12:28:58 +03:00
|
|
|
{
|
|
|
|
|
return new SmsRouter([
|
|
|
|
|
new SmscSmsProvider('l', 'p', ['*'], ['*' => 300]),
|
|
|
|
|
new MtsSmsProvider('t', ['mts'], ['*' => 400]),
|
|
|
|
|
]);
|
|
|
|
|
}
|
|
|
|
|
|
2026-07-23 12:34:02 +03:00
|
|
|
it('сырое имя МТС от ДаДаты сматчивается на канал МТС ТОЛЬКО через нормализацию', function () {
|
2026-07-23 12:28:58 +03:00
|
|
|
SalesAdAudiencePhone::create([
|
|
|
|
|
'phone' => '79990000010', 'expires_at' => now()->addDays(30),
|
|
|
|
|
'state' => 'active', 'operator' => 'ПАО "МТС"', 'phone_type' => 'mobile',
|
|
|
|
|
]);
|
|
|
|
|
|
2026-07-23 12:34:02 +03:00
|
|
|
// Роутер только-МТС: без нормализации 'ПАО "МТС"' не сматчится и номер уедет в skipped_no_route.
|
|
|
|
|
$selector = new SmsRecipientSelector(mts_only_router(), new OperatorNormalizer);
|
2026-07-23 12:28:58 +03:00
|
|
|
$plan = $selector->build(['79990000010']);
|
|
|
|
|
|
2026-07-23 12:34:02 +03:00
|
|
|
expect($plan->sendable)->toHaveCount(1)
|
|
|
|
|
->and($plan->skipped)->toBeEmpty();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('не-МТС номер при роутере только-МТС остаётся без маршрута (не навязываем чужой канал МТС-у)', function () {
|
|
|
|
|
SalesAdAudiencePhone::create([
|
|
|
|
|
'phone' => '79990000011', 'expires_at' => now()->addDays(30),
|
|
|
|
|
'state' => 'active', 'operator' => 'МегаФон', 'phone_type' => 'mobile',
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
$selector = new SmsRecipientSelector(mts_only_router(), new OperatorNormalizer);
|
|
|
|
|
$plan = $selector->build(['79990000011']);
|
2026-07-23 12:28:58 +03:00
|
|
|
|
2026-07-23 12:34:02 +03:00
|
|
|
expect($plan->sendable)->toBeEmpty()
|
|
|
|
|
->and($plan->skipped)->toBe(['79990000011' => SalesSmsMessage::SKIP_NO_ROUTE]);
|
2026-07-23 12:28:58 +03:00
|
|
|
});
|
|
|
|
|
|
2026-07-23 12:34:02 +03:00
|
|
|
it('при двух каналах чужой оператор уходит на универсал, МТС — на МТС', function () {
|
|
|
|
|
$n = new OperatorNormalizer;
|
|
|
|
|
expect(two_channel_router()->pick($n->canonical('ПАО "МТС"'))?->key())->toBe('mts')
|
|
|
|
|
->and(two_channel_router()->pick($n->canonical('МегаФон'))?->key())->toBe('smsc');
|
2026-07-23 12:28:58 +03:00
|
|
|
});
|