Commit Graph

4 Commits

Author SHA1 Message Date
Дмитрий 1d8723f285 feat(смс-клиент): Калининград и Камчатка получают СМС каждый в своё утро
Этап 3 «Время и цена», Task 2. Строки листа 3.1, 3.2 и первая половина 3.3.

У каждой строки снимка получателей появились две вещи: часовой пояс человека и момент,
раньше которого сообщение отдавать нельзя. Считается это ОДИН раз, при создании рассылки:
снимок сильнее всего (В-39), а на 20 000 номерах пересчёт на каждом витке джоба был бы
20 000 лишних расчётов.

Три состояния строки, и их важно не путать:
  — пояс известен, ждать нечего  → отдаём прямо сейчас;
  — пояс известен, время не пришло → ждёт своего утра;
  — пояса нет                     → ждёт уточнения региона и НЕ уходит вовсе (В-85).

Пустой пояс больше не означает «шлём по Москве». Он означает «мы не знаем, где человек
живёт», и такому номеру СМС не уходит. Про него при этом НЕ пишется в журнал рассылки
«нет маршрута»: мы его даже не пробовали отправить, и врать про него нельзя.

Рассылка, у которой часть номеров ещё ждёт, получает статус «ждёт утра» вместо «готово»,
и заморозка денег с неё не снимается — смета считалась на всех, оставшимся деньги ещё
понадобятся. Счётчик отправленного при этом обновляется: он считается из журнала, то есть
всегда правда, и человеку нужно видеть «отправлено 340 из 900» сразу, а не завтра (В-94).

Регион сделки читается из subject_code, а НЕ из region_code: последний в бою не пишет никто,
а в dev там демо-значения, и мы бы считали половину страны Тюменью — молча (В-82).

Прогоны: СМС 191/191 (было 186, 5 новых тестов), приём лидов 17/17, phpstan 0, pint чисто.
Вырезанием проверено дважды: убрал проверку «пояс известен» — покраснел тест про номер без
региона; убрал проверку «время пришло» — покраснели три теста про окно. Живьём на локальной
базе: две сделки (Москва и Камчатка) плюс пять демо-сделок без региона → ушёл один москвич,
Камчатке проставлено ожидание до 22:00 UTC (10 утра её времени), пятеро ждут региона,
рассылка висит «ждёт утра». Стенд возвращён как был.

В-93: у 19 старых тестов покраснение было закономерным — у их номеров нет региона. Боевой код
не ослаблял: фикстурам проставил регион и зафиксировал время прогона, иначе тесты зависели бы
от часа запуска. ⚠️ Ветку нельзя выкатывать между этой задачей и Task 5: пока ДаДата не начнёт
давать регион всем номерам, рассылка по своей базе и по списку руками отправит ноль.

Запись схемы v9.13.
2026-07-28 15:46:53 +03:00
Дмитрий c5943ebb4e feat(смс-клиент): снимок получателей — считаем смету и шлём по одному списку
Аудитория собиралась дважды: в контроллере для сметы и заново в джобе для
отправки. Между двумя сборками приходят новые лиды, и «посчитали 900,
отправили 917» было физически возможно.

Теперь контроллер, посчитав смету, кладёт получателей в
client_sms_campaign_phones (две новые колонки: operator, skip_reason), а джоб
читает этот снимок пачками по 500 и ничего не пересобирает.

Решение владельца В-39: после запуска список не пересматривается ничем,
включая стоп-листы — смета и факт сходятся копейка в копейку. Человек,
внесённый в «Не писать этим» уже после запуска, эту рассылку получит;
следующую — нет. Следствие названо и владельцем принято.

Попутно убран квадрат: проверка «номер уже отправлен» шла через in_array по
массиву — на 20 000 номеров это 400 млн сравнений.

Строки приёмочного листа 2.1 и 2.2.

Проверено: ClientSms 144/144, приём лидов 17/17, phpstan по своим файлам 0,
вырезание записи снимка красит все 4 новых теста, живой прогон — контакт,
добавленный между созданием и отправкой, СМС не получил.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-07-28 05:37:16 +03:00
Дмитрий b29a4ca4c4 revert(смс-клиент): отказ получателя убран целиком — решение владельца
Владелец: «нет такой функции и задачи нет, забудь о ней! пришла и пришла смс».
Причина — приписка «Отказ: liderra.ru/s/…» ставила НАШ адрес в рекламное СМС, которое
клиент шлёт своим покупателям: он рекламирует себя, а не нас.

Убрано: страница отказа /s/{token}, таблица коротких ссылок, сервис токенов, приписка
в тексте рассылки, колонка with_optout_link, ограничение частоты sms-unsubscribe,
три файла тестов, три миграции (на прод не выкатывались).

Осталось нетронутым: стоп-лист самого клиента «Не писать этим» и общий стоп-лист
портала — это другое, их владелец не отменял.

Строки приёмочного листа 1.6-1.13 срезаны, записано в «Чего эта работа НЕ делает» п.14
и в журнал вопросов В-30. Возражение про 38-ФЗ высказано владельцу и им отклонено.
Всё удалённое лежит в истории: коммиты 7aa30833 и 1dece3a2.

ClientSms 140/140, приём лидов 17/17.
2026-07-27 18:58:48 +03:00
Дмитрий f5483332e9 feat(смс-клиент): кнопка «Остановить» — после нажатия ни одного нового СМС
Клиент может остановить рассылку в очереди, на отправке и в ожидании утреннего окна.
Нажатие — это отметка «попросил остановить», а не мгновенный обрыв: сообщение, начатое
в этот момент, доводится до конца, сеть на полпути не рвём. Джоб читает отметку свежим
запросом перед каждым следующим номером.

Итог честный: статус «остановлена», причина «клиент», ушло столько, сколько в журнале,
списано ровно за это, заморозка снята полностью. Номера, до которых не дошли, в журнал
не пишутся — с ними ничего не произошло (В-27).

Строки приёмочного листа 1.14-1.17 (серверная часть; кнопка на экране — Task 10).
Защита проверена вырезанием: убрать выход из цикла — 2 красных теста.

ClientSms 151/151, приём лидов 17/17, phpstan по своим файлам чисто.
2026-07-27 18:28:58 +03:00