Commit Graph

11 Commits

Author SHA1 Message Date
Дмитрий e15a4d8a69 feat(прогрев ф2): тоггл «Греть здесь» и firmRow — на строки firm_channels
Фаза 2 Этап A, Task 8. toggle пишет строку firm_channels(channel, status=warming,
mode=funnel, warming_started_at=firm.warmup_started_at, warmed_times++) вместо
булева ch_*; off удаляет строку (инкремент двумя шагами, без raw). firmRow на
вкладке площадки считает state/warming_active по строке канала через
decideForChannelRow (нет строки или loaded → stopped/false). firms() eager-грузит
firmChannels (против N+1). Границы этапа A: warming_channels-бейджи, platformState,
channelColumn, allFirms и показ всех фирм — без изменений (ch_*, показ состава →
этап C). ch_* колонки не удаляются. Бамп baseline (+9 actingAs-ложняков).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 16:08:35 +03:00
Дмитрий 32f9d87f9c feat(прогрев ф2): файл МТС берёт только строки firm_channels warming+active
Фаза 2 Этап A, Task 7. mtsFile() выбирает фирмы по строке firm_channels
(channel=mts, status=warming) вместо флага ch_mts и решает по ней через
decideForChannelRow. Фирма с mts-строкой loaded в файл не попадает, даже с
ch_mts=true. Формат файла (streamDownload, имя, сортировка) без изменений.
Тронут только mtsFile — toggle/firmRow/firms остаются на Task 8.
Бамп phpstan-baseline (+2 к actingAs/$head TestCall-ложнякам на 2 новых теста).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-22 15:47:08 +03:00
Дмитрий 4d90168d75 feat(прогрев): файл МТС по срокам своей площадки
Task 8: mtsFile() отбирает фирмы решением PlatformWarmingDecider по
срокам ИМЕННО МТС (тем же приёмом, что SyncVkAudienceJob), вместо
плоского phone.state='active'. Фирма, погасшая по срокам МТС, в файл
больше не попадает, даже если у неё есть номер с state=active.
2026-07-22 11:18:40 +03:00
Дмитрий 39d460f8b6 test(прогрев): AdAudienceScreenTest под новый контракт days на строке площадки 2026-07-22 10:50:13 +03:00
Дмитрий 42462119f4 test(прогрев): переносит AdAudienceScreenTest на /api/sales/warming/{platform}
Старый /api/sales/ad-audience* снесён вместе с channels()-массовым
переключателем; экран теперь живёт по площадкам (yandex/vk/mts).
Тайлы (in_ads/expiring_week/waiting_sync) считаются теперь только
по номерам фирм, подписанных на площадку — тесты на тайлы привязывают
номера к firm_id фирмы с ch_yandex=true. segment_id/enabled/vk_status
переехали со state на построчную sales_ad_audience_platforms.
Два теста массовой простановки площадок (channels) убраны — capability
удалена, per-firm переключение уже покрыто AdAudiencePlatformApiTest.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-21 11:18:25 +03:00
Дмитрий 991af98c97 feat(sales): три галочки площадок и выгрузка файла для МТС
У МТС Маркетолога нет программного доступа к рекламе в Telegram (только SMS
API) — портал отдаёт готовый текстовый файл с номерами, начальник грузит
руками. channels() переписан под три независимых булевых поля вместо одной
строки; firms() отдаёт три признака вместо старого 'channels'.

Выгрузка берёт только активные (state=active), неудалённые (removed_at IS
NULL) номера фирм с ch_mts=true — иначе в МТС накопятся погашенные клиенты
и придётся платить за показы им.

Task 3 плана docs/superpowers/plans/2026-07-20-tri-ploshadki-i-mts.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 08:07:46 +03:00
Дмитрий 7e8d06e1aa feat(sales): состояние канала ВК на экране начальника
Контроллер отдаёт vk_status/vk_last_synced_at/vk_last_error из GET
/api/sales/ad-audience, экран показывает человеческим текстом: «доступ
ещё не выдан» / «ждёт объёма — нужно от 2000 номеров» / «работает».

Task 9 плана docs/superpowers/plans/2026-07-19-vybor-ploshadki-progreva.md.
2026-07-19 20:28:18 +03:00
Дмитрий aaeab9c62b feat(sales): массовая смена площадки прогрева
POST /api/sales/ad-audience/channels — начальник меняет channels
у отмеченных фирм разом (гейт denyIfNotHead, менеджеру 403).
firms() теперь отдаёт channels в списке.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
2026-07-19 19:43:16 +03:00
Дмитрий 79d1567e7d feat(sales): список прогрева и назначение менеджера из рекламы
Task 7 плана v2 (реклама на кандидатов): начальник видит список фирм
на прогреве (GET /api/sales/ad-audience/firms) и назначает менеджера
(POST .../assign) — из снимка фирмы рождается карточка «Потенциальные
клиенты» стадии new, реклама дальше следует за стадией карточки.
PATCH /api/sales/ad-audience теперь принимает все 11 сроков планировщика,
GET отдаёт их в durations.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 11:19:46 +03:00
Дмитрий 9bc587c2de fix(sales): реальный телефон директора убран из тестов и планов; клиент Яндекс.Аудиторий возвращён в main
Коммит d2c2ec43 от 19.07 оторвался от main (dangling, ни в одной ветке):
чистка ПДн и YandexAudienceClient в основную ветку так и не попали.
Номера заменены на фиктивные 7999000000X, клиент и его тесты внесены заново.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 10:24:21 +03:00
Дмитрий 44b892c771 feat(sales): экран «Реклама на кандидатов» в кабинете начальника
GET/PATCH /api/sales/ad-audience — три числа (в рекламе сейчас, выходят на
этой неделе, ждут отправки), рубильник и срок хранения номера. Доступ только
роли head — гейт denyIfNotHead зеркалит SalesManagersController.

Экран объясняет обычными словами, что список пополняется только кнопкой
«Отправить в рекламу» в Поиске клиентов, и предупреждает, когда номеров
меньше 100 (Яндекс не запустит рекламу).

Тесты: 9 в tests/Feature/Sales/AdAudienceScreenTest.php (доступ, три числа,
смена настроек, валидация срока). SharesSupplierPdo — модели на pgsql_supplier.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-19 08:46:36 +03:00