Исходная ситуация
Понедельник, утро. Кто-то открывает пять вкладок: рекламный кабинет, веб-аналитику, выгрузку из базы, банк-клиент, трекер задач. Переносит числа в таблицу, красит ячейки, пишет два абзаца комментария, отправляет в чат.
Уходит полдня. Через неделю операция повторяется целиком.
Дальше начинаются расхождения. Число из рекламного кабинета не сходится с числом из аналитики, потому что периоды считаются по разным часовым поясам. Выручка за месяц выглядит провальной, потому что поступление от платёжного агрегатора приходит в начале следующего месяца. Через квартал никто не может объяснить, откуда взялась цифра в старом отчёте: вкладка закрыта, а кабинет пересчитал данные задним числом.
Худший вариант — отчёт, который читают по инерции. Числа собираются, рассылаются, и ни одно решение по ним не принимается.
Что смотрели
Замер времени сборки. Не оценка по памяти, а засечка от открытия первой вкладки до отправки. Оценки по памяти систематически занижены вдвое.
Инвентаризация чисел. Каждая строка отчёта помечается: принималось ли по ней хоть одно решение за последний квартал. Строки без решений — кандидаты на удаление, а не на автоматизацию.
Сверка определений. Для каждой метрики выписывается, что она значит. Почти всегда выясняется, что «активный клиент» у маркетинга и у финансов — разные множества, а «лид» в рекламном кабинете и в CRM считаются по разным событиям. До письменного определения автоматизировать нечего.
Часовые пояса и границы суток. Каждый источник отдаёт данные в своей зоне: один считает сутки по UTC, другой по локальному времени, третий по времени аккаунта. Расхождение в несколько процентов обычно объясняется здесь, а не ошибкой в данных.
Сдвиг денежных поступлений. Когда эквайринг перечисляет сборы за месяц в начале следующего, календарное окно недосчитывает месяц выручки, и сравнение год к году разъезжается. Окно сдвигается один раз и фиксируется в определении метрики.
Что поменяли
1. Словарь метрик прежде кода. Файл, где для каждой метрики записано: человеческое определение, источник, точная формула или SQL, единица измерения, окно расчёта. Метрика без записи в словаре в отчёт не попадает.
2. Каждый источник читается через API. Рекламный кабинет, аналитика, банк, база, трекер — программно и по расписанию. Ручная выгрузка и разбор интерфейса браузером не используются: первое не воспроизводится, второе ломается при ближайшем редизайне.
3. Слой снимков. Результат каждого запроса сохраняется как есть, с меткой времени и параметрами запроса. Отчёт собирается из снимков. Без этого слоя вчерашний отчёт нельзя пересобрать, потому что источники пересчитывают данные задним числом.
4. Единый временной канон. Одна таймзона отчёта, границы периодов вычисляются в одном месте кода, все источники приводятся к ней при чтении, а не при сборке.
5. Числа считает код. SQL и скрипты по формулам из словаря. Модель к арифметике не подпускается.
6. Модель работает на последнем шаге. Она описывает, что изменилось относительно прошлого периода и прошлого года, и отмечает аномалии. Выводы и решения остаются за человеком.
7. Проверки перед публикацией. Сумма частей сходится с целым. Отклонение от прошлого периода больше порога — число помечается как требующее взгляда, а не уезжает молча. Источник не ответил — в отчёте стоит «нет данных», а не ноль. Ноль вместо пропуска порождает ложные выводы.
8. Прошлый год рядом с текущим. Всегда, без отдельной просьбы. Сезонность в большинстве бизнесов сильнее недельных колебаний.
9. У каждого числа паспорт. Рядом со значением: источник, время снимка, ссылка на определение в словаре. Через полгода вопрос «откуда это» закрывается за секунды.
10. Документ, а не сообщение. Скрипт формирует файл с датой в имени и кладёт его в хранилище. В чат уходит заголовок, несколько ключевых строк и ссылка. Длинная таблица в мессенджере не читается.
11. Одна точка входа. Расписание и ручной запуск дёргают одну и ту же команду. Разные триггеры, один код.
Что не трогали
- Сами источники. Данные читаются на месте. Строить отдельное хранилище ради еженедельного отчёта — работа на порядок больше при том же результате.
- Существующие дашборды. Они решают другую задачу: смотреть в моменте. Отчёт фиксирует состояние на дату.
- Ручной комментарий руководителя. Остался отдельным разделом в конце документа. Автоматика описывает изменения, оценку даёт человек.
- Прежний формат на переходный период. Таблица собиралась руками параллельно, пока автоматический отчёт не сошёлся с ней несколько раз подряд.
Обратимость
- Расписание отключается, команда ручного запуска остаётся прежней, отчёт продолжает собираться.
- Снимки сохраняются независимо от сборки. Даже при полном откате остаётся история данных, и отчёт за прошлые даты пересобирается.
- Комментарий модели за флагом. Выключается, остаются числа и таблицы.
- Словарь метрик переживает откат любой автоматики. Он полезен сам по себе и остаётся, даже если скрипты выброшены.
- Каждая версия отчёта хранится файлом. Сравнение двух версий показывает, что поменялось и в цифрах, и в коде.
Границы
- Источник без API. Разбор интерфейса живёт до ближайшего редизайна. Если данные нужны надолго, сначала решается вопрос доступа.
- Метрика без согласованного определения. Автоматизация зафиксирует одну из сторон спора и придаст ей вид истины. Спор решается до кода.
- Данные с задержкой закрытия. Бухгалтерские и сверяемые показатели становятся окончательными позже, чем выходит отчёт. Для них в документе нужна пометка «предварительно».
- Регламентированная отчётность. Налоговая, статистическая, аудиторская — там свои формы, сроки и ответственность.
- Отчёт ради отчёта. Если по числам не принимаются решения, автоматизация даст тот же бесполезный документ, только быстрее и чаще.
Правило: числа считает код по письменному определению, каждый ответ источника сохраняется снимком, а модель только описывает изменения.
