Files
portal/app/database
Дмитрий 73bd36b6ce feat(телеграм-реклама): Этап 3.1 — id кампании МТС хранится рано и при отказе (+ разведка экрана отказа)
Этап 3 «Жизненный цикл и модерация», задача 3.1. Плюс закрыта задача 3.0
(живая разведка экрана отказа) — вердикт МТС по кампании «займ» (2231134)
пришёл: «Отклонена». Разведка read-only, деньги не тронуты.

Задача 3.1 — колонка mts_campaign_id + РАННЕЕ и надёжное сохранение:
- Миграция client_tg_campaigns.mts_campaign_id (varchar(32) NULL, после
  status_reason) + запись CHANGELOG_schema v8.89 (предварит., ветка). RLS не
  меняется; rls-reviewer не требуется (nullable-колонка данных).
- Робот (Node): чистый хелпер parseCampaignId(url) в cabinet.js (покрыт
  тестом); runner.js захватывает id СРАЗУ после создания черновика (шаг
  аудитории) и печатает маркер MTS_CAMPAIGN_ID=<id> в stderr; id теперь
  идёт и в ветке ОТКАЗА (раньше терялся).
- Обёртка (PHP): TelegramRobotRunner восстанавливает id из stderr-маркера во
  всех путях (таймаут/непарсабельный вывод/JSON без id); RobotResult::failed
  принимает id.
- Джоб: finalize сохраняет mts_campaign_id при ЛЮБОМ исходе (успех/отказ), не
  затирая ранее сохранённый id. Метод failed() не трогали — туда результат не
  доходит (осознанный residual, закроют уборщик 3.1b и sweeper 3.3).

Разведка отказа (3.0) записана в bots/mts-telegram-ads/FLOW-FINDINGS.md:
причина показана текстом в слайд-модалке «Причины отклонения кампании»
(кнопка «Причины»); поля загрузки файла на экране отказа нет — документ
грузится через «Исправить» → шаг «Сообщение» → «Комментарий для модератора»;
кнопка пересдачи — «Исправить».

TDD, робот замокан, тесты на liderra_testing (номера 7999…).
Приёмка: Node 48/48 (npm test), Pest ExternalIdTest 2/2 + регрессия ClientTg
122/122, phpstan (4 боевых файла) 0, deptrac 0 нарушений, pint чисто.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-28 08:49:01 +03:00
..