naming`). */ uses(DatabaseTransactions::class); function makeSenderFor(?array $operators, string $status = ClientSmsSender::STATUS_ACTIVE, string $name = 'mybrand.ru'): Tenant { $tenant = Tenant::factory()->create(); ClientSmsSender::create([ 'tenant_id' => $tenant->id, 'name' => $name, 'name_type' => ClientSmsSender::TYPE_WEBSITE, 'status' => $status, 'operators' => $operators, 'monthly_fee_rub' => '0.00', 'consent_at' => now(), ]); return $tenant; } it('своего имени нет вовсе — отдаёт пустую строку, чтобы канал подписался своим', function () { $tenant = Tenant::factory()->create(); expect(app(ClientSmsSenderResolver::class)->forOperator($tenant->id, 'tele2'))->toBe(''); }); it('имя согласовано у этого оператора — отдаёт его', function () { $tenant = makeSenderFor(['mts', 'tele2']); expect(app(ClientSmsSenderResolver::class)->forOperator($tenant->id, 'tele2'))->toBe('mybrand.ru'); }); it('имя согласовано у ДРУГОГО оператора — своим именем не подписывает', function () { $tenant = makeSenderFor(['mts']); // Ровно тот случай, что дал живой отказ Теле2 04.08.2026. expect(app(ClientSmsSenderResolver::class)->forOperator($tenant->id, 'tele2'))->toBe(''); }); it('список операторов не заполнен — считаем, что имя годится всем', function () { // Старые записи заведены до появления разбора по операторам: отнять у них // имя молча — значит поменять поведение задним числом. $tenant = makeSenderFor(null); expect(app(ClientSmsSenderResolver::class)->forOperator($tenant->id, 'megafon'))->toBe('mybrand.ru'); }); it('имя ещё на согласовании — не подписывает им', function () { $tenant = makeSenderFor(['tele2'], ClientSmsSender::STATUS_PENDING); expect(app(ClientSmsSenderResolver::class)->forOperator($tenant->id, 'tele2'))->toBe(''); }); it('имя приостановлено за долг — не подписывает им', function () { $tenant = makeSenderFor(['tele2'], ClientSmsSender::STATUS_SUSPENDED); expect(app(ClientSmsSenderResolver::class)->forOperator($tenant->id, 'tele2'))->toBe(''); }); /** * Решение владельца 05.08.2026: если у клиента СВОЁ имя есть, но у этой сети оно * не согласовано — номер не уходит вовсе. Молча подписать чужую рассылку нашим * «Liderra.ru» нельзя: клиент платил за свой бренд и об этой подмене даже не * узнал бы (журнал сообщений имя отправителя не хранит). * * Так уже работает отдел продаж (SmsRecipientSelector → SKIP_NO_SENDER), и надпись * на клиентском экране («нет имени отправителя для оператора») давно готова. */ it('своего имени нет вовсе — НЕ блокируем: шлём от имени Лидерры, как и раньше', function () { $tenant = Tenant::factory()->create(); expect(app(ClientSmsSenderResolver::class)->blocksOperator($tenant->id, 'tele2'))->toBeFalse(); }); it('имя согласовано у этого оператора — не блокируем', function () { $tenant = makeSenderFor(['mts', 'tele2']); expect(app(ClientSmsSenderResolver::class)->blocksOperator($tenant->id, 'tele2'))->toBeFalse(); }); it('имя есть, но у ЭТОГО оператора не согласовано — блокируем', function () { $tenant = makeSenderFor(['mts']); expect(app(ClientSmsSenderResolver::class)->blocksOperator($tenant->id, 'tele2'))->toBeTrue(); }); it('список операторов не заполнен — не блокируем', function () { $tenant = makeSenderFor(null); expect(app(ClientSmsSenderResolver::class)->blocksOperator($tenant->id, 'megafon'))->toBeFalse(); }); it('имя приостановлено — не блокируем: это как если бы своего имени не было', function () { // Иначе долг за имя останавливал бы рассылку целиком, а не возвращал её к // имени Лидерры. Останавливать — отдельное решение, здесь его не принимаем. $tenant = makeSenderFor(['mts'], ClientSmsSender::STATUS_SUSPENDED); expect(app(ClientSmsSenderResolver::class)->blocksOperator($tenant->id, 'tele2'))->toBeFalse(); }); it('чужое имя соседа не подставляет', function () { makeSenderFor(['tele2'], ClientSmsSender::STATUS_ACTIVE, 'sosed.ru'); $mine = Tenant::factory()->create(); expect(app(ClientSmsSenderResolver::class)->forOperator($mine->id, 'tele2'))->toBe(''); });