Files
portal/app/resources
Дмитрий 00cc072e2f feat,телеграм-реклама: «Моя база номеров» заработала — пункт больше не ведёт в никуда
Это снимает запрет на выкат телеграм-рекламы.

Пункт «Моя база номеров» стоял в выборе аудитории с 27.07, а писать в таблицу
client_tg_contacts не умела НИ ОДНА строка кода: ни экрана загрузки, ни серверной
ручки, ни переноса из сделок. У любого клиента пункт всегда показывал ноль.
Клиент выбрал бы «свою базу», увидел пустоту и решил, что портал потерял его
клиентов. Песочница выключена, деньги живые — катить в таком виде было нельзя.

Читающая половина при этом была готова с самого начала: TelegramAudienceService
умеет и нормализацию, и схлопывание дублей, и вычитание стоп-листа. Не хватало
только записи, поэтому работа вышла куда меньше, чем казалось.

Сервер:
- TelegramBazaService — разбор файла, замена базы, очистка. Номер берётся по
  одному в строке либо первым столбцом таблицы, разделители запятая, точка с
  запятой, табуляция. Мусорные строки не роняют разбор, а считаются отдельно.
- три ручки: GET, POST и DELETE /api/telegram/contacts.
- потолок 200 000 номеров и 10 МБ на файл; обрыв по потолку не молчит, а
  возвращается признаком.

Экран, в шаге «Кому показываем»:
- сколько номеров в базе, заливка файла, очистка;
- итог заливки целиком: принято, повторов, не похоже на номер. «Принято 1200»
  без остального читалось бы как «файл зашёл полностью»;
- после заливки счётчик охвата пересчитывается сам.

Решения, которые стоит знать:
- заливка ЗАМЕНЯЕТ базу, а не добавляет. Так предсказуемее: клиент держит базу у
  себя и заливает заново. Подмешивание копило бы номера, от которых он не смог бы
  избавиться — построчного удаления в интерфейсе нет. На экране это написано до
  нажатия, молчаливой потери нет.
- файл без единого годного номера отклоняется, старая база остаётся цела. Иначе
  клиент залил бы файл не того формата и потерял всё.
- замена сделана удалением и вставкой, а не upsert: право UPDATE на таблице не
  выдано, upsert упёрся бы в это на бою и молча правил бы ноль строк.
- наружу отдаём только счётчики. Номера — персональные данные, экрану они не
  нужны и в ответах не появляются.

Приёмка: 12 тестов сервера и 9 тестов экрана, все до кода и все красные по верной
причине — сервер отвечал 405, блока на экране не было.

Замеры: телеграм-модуль 325 тестов 0 падений, экраны 244 файла 1855 тестов
0 падений, статанализ 0, форматтер чисто. Проверка типов 6 ошибок, все чужие,
столько же было до работы.

Для выката, проверить на бою: право USAGE на счётчике client_tg_contacts_id_seq.
Замерил в тестовой базе — счётчик без права, но ровно так же выглядит и счётчик
client_tg_campaigns_id_seq, в который портал на бою пишет. То есть новых прав эта
работа не требует, но проверка дешёвая, а пропущенный grant на бою даёт отказ,
которого на dev не видно.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-02 23:13:31 +03:00
..