a39694e11b
Этап 1 «Нельзя обжечься», задачи 1–3 приёмочного листа (docs/superpowers/2026-07-27-PRIEMKA-client-sms-fixes.md, строки 1.4, 1.4а, 1.5). - новая таблица sms_global_optouts (SaaS-уровень, RLS намеренно нет: номер закрывается у всех тенантов сразу — защита договора с МТС при жалобе); - ClientSmsRecipientSelector отсеивает такой номер ПЕРВЫМ, раньше тенантского стоп-листа: наше обязательство перед оператором сильнее настроек клиента; - клиенту причина видна словами — «номер закрыт администрацией», а не молчаливое «не отправлено» (решение владельца, вопрос В-2 листа); - админ-адреса /api/admin/sms/global-optouts: внести (номер в любом виде), список, убрать; непонятый номер отклоняется внятно; - запись v9.00 в db/CHANGELOG_schema.md. Проверено: ClientSms 122/122, приём лидов 17/17, phpstan по своим файлам 0, gitleaks чисто. Защита доказана вырезанием — без отсева падают ровно 3 теста. Живого прогона строк 1.4/1.5 ещё нет: админ-экран идёт задачей 10. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
45 lines
1.6 KiB
PHP
45 lines
1.6 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
use App\Models\SmsGlobalOptout;
|
|
use Illuminate\Database\QueryException;
|
|
use Illuminate\Foundation\Testing\RefreshDatabase;
|
|
|
|
/**
|
|
* Общий стоп-лист портала (строка листа 1.4): номер, закрытый владельцем,
|
|
* перестаёт получать СМС у ВСЕХ клиентов сразу. Это защита договора с МТС,
|
|
* а не удобство одного клиента, — поэтому таблица общая, без изоляции по тенанту.
|
|
*/
|
|
uses(RefreshDatabase::class);
|
|
|
|
it('хранит номер в общем стоп-листе и находит его', function () {
|
|
SmsGlobalOptout::create([
|
|
'phone' => '79001112233',
|
|
'reason' => 'жалоба оператору',
|
|
]);
|
|
|
|
expect(SmsGlobalOptout::where('phone', '79001112233')->exists())->toBeTrue();
|
|
});
|
|
|
|
it('не допускает дубля номера', function () {
|
|
SmsGlobalOptout::create(['phone' => '79001112233']);
|
|
|
|
expect(fn () => SmsGlobalOptout::create(['phone' => '79001112233']))
|
|
->toThrow(QueryException::class);
|
|
});
|
|
|
|
it('хранит причину и автора записи', function () {
|
|
SmsGlobalOptout::create([
|
|
'phone' => '79001112244',
|
|
'reason' => 'жалоба абонента',
|
|
'created_by' => 77,
|
|
]);
|
|
|
|
$row = SmsGlobalOptout::find('79001112244');
|
|
|
|
expect($row->reason)->toBe('жалоба абонента')
|
|
->and($row->created_by)->toBe(77)
|
|
->and($row->created_at)->not->toBeNull();
|
|
});
|