ac16861b87
Статус launched был терминальным: конца у рекламы не существовало вовсе. Отсюда две беды разом — робот ходил за цифрами вечно, а неоткрученные деньги возвращать было некуда. Живая улика, кампания №15: списано 255,36 ₽ за 380 показов, показан 21, площадка израсходовала 10,08 ₽. Переплата 241,25 ₽ не вернулась бы никогда. Портал честно читал stats_spend_rub и не использовал его нигде. Ш1 робот перестаёт долбиться в потерянные кампании: 5 неудач подряд уводят в разбор, считаются только заходы после последней правки строки кампании Ш2 статус кабинета доезжает до портала; незнакомое слово идёт в журнал Ш3 новый статус completed «Показы закончились», переход launched → completed Ш4 суточная задача в 04:40 закрывает отработавшую рекламу и возвращает переплату; возврат идемпотентен ключом tg:campaign:ID:vozvrat, неизвестный расход не закрываем Ш5 тревога в журнал, если заморозка денег висит дольше суток Попутно вскрыто и починено: разбор кампании писал клиенту «деньги вернулись на рекламный кошелёк», не вернув ни рубля. Новый вход в старый узел сделал его сообщение ложью. Новая колонка client_tg_campaigns.spend_changed_at — двигается только при реальном изменении суммы; stats_read_at для этого не годится, он растёт на каждом заходе робота. Журнал схемы v9.74. Кнопка «Остановить» не сделана, закрытие по слову кабинета тоже: разведка 08.08 показала, что кабинет говорит «Останавливается, до 30 минут», но итогового слова мы так и не узнали, а вернулись ли деньги — не замерено. Подробности и что делать дальше — в плане. На боевой не выкачено: нужна миграция и разрешение владельца. Сторожа: ClientTg 438 зелёных, экраны телеграма 47 зелёных. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>