Files
portal/app/tests/Feature
Дмитрий 61be447b41 fix(реклама): Директ отвергал запрос числа показов, а портал читал отказ как ноль
Самая тяжёлая находка смены, вылезла из вопроса владельца «показано 0, почему?
там один же есть» — из сверки карточки с кабинетом глазами.

Замер на боевом: запрос портала к Директу отвергается с кодом 400 — «В params
отсутствует обязательное поле IncludeVAT». А код ответ не проверял: брал тело,
переводил в число и получал ноль. То есть «показов не было» — не факт, а
проглоченная ошибка.

Чем накрывается. Это единственный источник числа показов, и у него две работы:
число «Показано» на карточке и основание списать деньги за открученную рекламу.
Значит ни за один показ клиенту не выставлялся счёт — реклама шла за наш счёт.
И тихий ноль опасен сам по себе: затирает настоящее число на карточке, а при
истёкшем сроке закрывает кампанию с возвратом всей заморозки.

Почему не поймали раньше: ноль выглядит как «показов ещё не было» — законное
состояние новой кампании. Отличить «не было» от «не смогли спросить» портал не
умел. На этом месте с самого начала висел TODO про сверку формата перед боем.

Три правила и три сторожа:
- IncludeVAT в запросе — без него Директ отвергает запрос целиком;
- processingMode auto — иначе отчёт строится в фоне и приходит пустое тело;
- громкая ошибка вместо тихого нуля при не-2xx и нечисловом ответе.

Наверху ошибка уже обработана правильно: обход пишет предупреждение и идёт
дальше, а «Пауза» при такой ошибке не отпускает деньги.

Четвёртая мина, вскрытая сторожем уникальности: имя отчёта строилось из секунд,
два вызова в одну секунду получали одно имя и второй читал кэш первого. Добавлен
случайный хвост.

Настоящий ноль из Яндекса остаётся нулём — отдельный сторож держит и это.

Прогон: 393 сторожа блока рекламы, статанализ 0, стиль чист. Схема не менялась.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-04 18:13:25 +03:00
..