Перейти к содержимому
VC
Кейс 15 из 33 · Интернет-торговля · аналитика

Сверка выручки из трёх источников: разрыв 8,4% объяснён до 0,33%

У бренда товаров для активного отдыха из США три источника называли выручку одним словом и давали три разных числа: оперативная книга владельца, складская книга товароведа и собственная CRM. Разовая тройная сверка объяснила разрыв по сайту и нашла сломанное сравнение год к году. Затем сверка стала суточной задачей с порогом 3% и правилом: при охвате ниже 70% вердикт не выносится.

Отрасль
Интернет-торговля · два магазина на Shopify
Стек
Python · Shopify Admin API · Google Sheets API · systemd
Сроки
Разовая сверка — 1 день, постоянный контур — неделя
Итог
разрыв 8,4% → остаток 0,33%
01 · Боль

Три отчёта, три выручки и спор о том, чьим верить

Владелец сводит продажи по дням в своей Google-таблице: два магазина, два маркетплейса, расход по каналам. Товаровед ведёт складскую книгу: строка на каждую позицию заказа, закупочная цена, логистика, разметка канала. CRM считает по данным Shopify напрямую. За одни и те же 19 дней три источника показали три разные выручки по сайту, и разрыв между книгой владельца и CRM составил 8,4%.

Вопрос владельца звучал буквально: «почему эти данные не совпадают с данными из Shopify?» Пока ответа нет, любое решение по бюджету упирается в спор о цифрах: у каждой стороны свой отчёт, и каждая права внутри своих определений.

В той же таблице стояло сравнение год к году: −12,84% по общей выручке. На него смотрели как на падение бизнеса.

02 · Решение

Один код, одно окно, каждое расхождение до заказа

Работа шла в два этапа. Сначала разовая тройная сверка, которая закрыла спор о цифрах и дала владельцу письменную сводку. Затем та же сверка превратилась в постоянную задачу со снимком и порогом, а свежий код прошёл состязательный аудит.

01
Тот же код

Shopify опрашивается за то же окно теми же функциями, что считают CRM: у сверки и у отчёта одна арифметика

02
Построчный разбор

Каждое расхождение доведено до конкретных заказов: отмены, частичные возвраты, граница суток

03
Третий источник

Складская книга товароведа сведена с CRM по каждому источнику продаж: сайт, два маркетплейса

04
Год к году на равных окнах

19 дат текущего года сравниваются с теми же 19 датами прошлого, без полного месяца в знаменателе

05
Сводка владельцу

Шесть разделов; отдельно помечено, что взято из отчётов сторон и что проверено по первичным данным

Две величины под одним словом

Разрыв по сайту в 8,4% сложился ровно из отменённых и частично возвращённых заказов. Книга владельца хранит сумму в момент заказа, CRM показывает деньги после отмен и возвратов. Обе цифры верны и отвечают на разные вопросы: сколько наторговали и сколько денег осталось. Остаток 0,33% приходится на заказы у границы суток. Попутно закрыт пробел в самой CRM: правило «отменённый и полностью возвращённый заказ в выручку не входит» работало, а частично возвращённый заказ входил целиком — за 30 дней таких заказов 7, 0,47% суммы. Теперь возврат вычитается и печатается отдельной строкой, чтобы у менеджеров, которые видят в своей таблице первоначальную сумму заказа, было объяснение.

Складская книга: сверка стала суточной задачей

В первый день складская книга была сведена с CRM руками, в файл во временной папке, и назавтра сверки уже не существовало. Модуль сверки делает её постоянной: читает книгу выгрузкой диапазона, считает выручку и себестоимость по каждому источнику продаж, сравнивает построчно с Shopify тем же кодом, что считает CRM, и кладёт снимок в файл. Страницы CRM читают снимок: прямое чтение книги стоило бы выгрузки в 16 тысяч строк при каждом открытии. Задача запускается по суточному таймеру. Порог расхождения 3% при измеренных 0,6% оставляет запас на границу суток и ручные правки. При расхождении задача завершается штатно и печатает разницу; служба падает в одном случае — когда сверка не состоялась, и тогда тревога уходит в чат команды.

Книги — рабочий инструмент товароведа, поэтому модуль работает только на чтение: две проверки в тестах читают текст модуля и подтверждают, что функций записи в нём нет.

Четыре итерации разбора причин

Первый живой прогон дал по итогу сайта +0,62% и красные строки по магазинам. Каждую причину пришлось найти на совпавших заказах:

  • книга хранит цену до скидки, Shopify — оплаченную сумму; теперь книга сравнивается с суммой «оплачено плюс скидка», и совпадение проверено поштучно
  • у части заказов в книге есть строка с непроставленной ценой — бесплатные аксессуары; такой заказ выводится из сравнения с обеих сторон, а размер пробела пишется в снимок отдельным полем
  • «ручные» заказы — понятие CRM, в книге они лежат под обычным магазином; при сравнении они складываются обратно в свой магазин
  • книга пишет номера заказов одного магазина с ведущим нулём; до нормализации 100 заказов из 158 выглядели отсутствующими, после неё сошлись 153 из 158

После четырёх итераций сверка встала: −0,81% по одному магазину, −0,12% и 0,00% по маркетплейсам при пороге 3%. По одному из маркетплейсов сошлись все 62 заказа из 62, ни одного потерянного ни с одной стороны.

Состязательный аудит кода суточной давности

Через несколько дней модуль разобрали независимые агенты-проверяющие с одной задачей: найти, что в нём неверно. Итог — 68 находок, 42 подтверждены, 11 дефектов в коде, написанном накануне. Каждый воспроизведён до починки и закрыт тестом, а каждый тест проверен возвратом ошибки в код: тест краснеет.

  • окно запрашивалось в UTC и фильтровалось по локальной дате магазина: 154 заказа из 959 попадали на границу суток, 15% денег; однодневное окно показывало расхождение 15% при исправной книге. Теперь окно берётся с запасом в сутки с обеих сторон и фильтруется по запрошенным датам
  • строка списания брака уходила в продажи из-за точного сравнения текста, и маржа 50,0% превращалась в 59,3%; теперь категория читается по началу строки
  • источник продаж сопоставлялся с учётом регистра: одна строчная буква в колонке, которую заполняет человек, давала «разошлось» при исправной книге
  • цена позиции из книги сравнивалась с итогом заказа вместе с налогом и доставкой; теперь сравнение идёт с суммой позиций
  • модуль отвечал «сошлось» при полном отказе своей стороны: в книге есть деньги, Shopify не ответил, список расхождений пуст. Теперь «сошлось» требует хотя бы одной сверенной строки и ни одной несверенной
  • вердикт не смотрел на охват: искусственные данные аудита — 101 заказ, у 100 из них строка без цены — давали «сошлось» по 0,25% денег. Теперь охват печатается в снимке, и ниже 70% вердикт не выносится
  • снимок печатал «деньги вне сравнения» как стоимость затронутых заказов — в пять раз больше настоящей суммы расхождений; теперь это три отдельных поля
  • маржа считалась по смешанным наборам строк; теперь только по строкам, где прочитаны и цена, и закупочная

Тестов у модуля стало 33: было 15 в день запуска и 24 после разбора причин. Значения в тестах сняты с живой книги.

Снимок вышел на экран

Аудит отметил и организационный дефект: снимок сверки писался в файл, который не открывал ни один человек. Сигнал, которого никто не видит, ничего не защищает. Теперь карточка «Книги склада» на странице интеграций CRM показывает по каждой строке сумму книги, сумму Shopify, расхождение и вердикт, а рядом — охват сравнения и маржу по закупочной.

03 · Стек

Тот же код, что считает CRM, и только чтение чужих книг

Python

Модуль слоя отчётности; выручка по Shopify считается теми же функциями, что и в CRM

Shopify Admin API

Заказы обоих магазинов за окно с запасом в сутки с обеих сторон, фильтр по локальной дате магазина

Google Sheets API

Складская книга читается выгрузкой диапазона; две проверки в тестах подтверждают отсутствие функций записи в модуле

Снимок в JSON

Результат сверки лежит в файле; страницы открывают его мгновенно, книга при этом не выгружается

systemd: таймер и служба тревоги

Суточный запуск; служба падает только при несостоявшейся сверке, тревога уходит в чат команды

pytest

33 теста, значения ячеек сняты с живой книги; каждая починка проверена возвратом ошибки в код

Состязательный аудит

Независимые агенты-проверяющие ищут ошибки в свежем коде: 68 находок, 42 подтверждены

Google-таблица владельца

Сверена на том же окне; ошибка год к году найдена пересчётом на равных окнах

PythonShopify Admin APIGoogle Sheets APIJSONsystemdpytestAdversarial audit
04 · Результат

Спор о цифрах закрыт, сверка работает каждый день

Разрыв по сайту
8,4% 0,33%

остаток приходится на заказы у границы суток

Год к году
−12,84% ≈ +30%

19 дат делились на полный месяц прошлого года

Аудит модуля сверки
11

дефектов в коде суточной давности: 68 находок, 42 подтверждены

Обе цифры верны, и теперь у них разные имена

Разрыв по сайту в 8,4% объяснён полностью: отменённые заказы плюс частичные возвраты, остаток 0,33% приходится на границу суток. Складская книга сошлась с CRM на 0,6%; один маркетплейс совпал точно, по второму все три источника сходятся в пределах 3,5%. Одна оговорка сделана вслух: строки в складскую книгу попадают из Shopify — руками и через наш же конвейер заказов в таблицы склада, поэтому совпадение на 0,6% подтверждает точность переноса: ни одного потерянного заказа, ни одной задвоенной суммы. Независимая часть книги — закупочная цена и логистика, которых больше нигде нет.

Падение −12,84% оказалось ростом около +30%

В таблице строка текущего августа складывалась из 19 дат, а строка прошлого года держала полный месяц, и 19 дней делились на 31. На одинаковых окнах, с 1 по 19 августа обоих лет, выручка сайта выросла на 29%, вместе с маркетплейсами — на 30%. Владелец получил сводку на шесть разделов, где отдельно помечено, что взято из его отчётов и что проверено по первичным данным. Одно моё утверждение снято в самой сводке: в первой версии значилось, что расход по одному каналу в таблице отсутствует; чтение всех 37 колонок нашло его, и он совпал с расходом по счёту площадки на 0,04%. Вывод из отсутствия данных требует доказать полноту чтения.

Сверка стала суточной задачей

После четырёх итераций разбора причин строгие строки сошлись: −0,81% / −0,12% / 0,00% при пороге 3%. Живой прогон через неделю после запуска: 701 строка, расхождения +2,18% / −0,02% / +0,00%, вердикт «сошлось». Снимок открывается на странице интеграций CRM мгновенно, вместе с охватом сравнения и маржой по закупочной.

Вердикт выносится только при достаточном охвате

Правило, которое переживёт этот проект: измеренный ноль отличается от невозможности измерить. «Сошлось» теперь означает, что ни одна строка не разошлась, хотя бы одна реально сверена, несверенных нет и сравнением накрыто не меньше 70% денег. Ниже этого порога вердикт не выносится, и на экране стоит «не сверено». Полный отказ своей стороны читается как отказ, пустой знаменатель даёт прочерк.

Итог для владельца: спор «чьи данные верны» закрыт, каждое расхождение объяснено до конкретных заказов, а сверка стала ежедневной и проверяемой. Сквозная атрибуция отвечает, какая реклама приносит заказы; эта работа отвечает, каким цифрам о деньгах верить.

05 · Применимость

Где ещё ложится та же методология

За кейсом стоит типовая задача «две-три учётные системы называют одним словом разные числа». Методика переносится везде, где отчёты собираются из нескольких источников:

  • Магазин плюс маркетплейсы — витрина показывает сумму заказа, маркетплейс перечисляет выплату за вычетом комиссии; складывать их в один итог можно после приведения к одной величине
  • Учёт в 1С, CRM и банке — выручка по отгрузке, по оплате и по поступлению расходятся по определению, и спор решается сверкой на одном окне
  • Отчёты, собираемые руками в таблицах — сравнение периодов на разных окнах, неполный месяц в числителе при полном в знаменателе, суммы колонок без фильтра по типу строки
  • Складские и закупочные книги как единственный источник себестоимости — сверка с продажами даёт настоящую маржу
  • Аудит существующей отчётности перед решениями по бюджету — до того, как «падение» в таблице приведёт к сокращению работающего канала
Что переиспользуется на следующих проектах
  • Сверка тем же кодом, что считает основной отчёт: у отчёта и у проверки одна арифметика
  • Правило охвата: вердикт выносится, когда сравнением накрыта достаточная доля денег; измеренный ноль отличается от невозможности измерить
  • Снимок в файл плюс страница, которая его показывает; суточный таймер; падение задачи только при несостоявшейся сверке
  • Доступ к чужим рабочим книгам только на чтение, закреплённый тестами по тексту модуля
  • Состязательный аудит свежего кода: воспроизвести, починить, закрыть тестом, проверить тест возвратом ошибки
  • Сводка заказчику с явным разделением: что взято из отчётов сторон, что проверено по первичным данным
Похожая задача?

Если три отчёта дают три выручки — это сверяется до заказа

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

Готовы начать?

Аудит за 9 900 ₽ — с конкретным отчётом и сметой

Расскажу что внедрить в вашем бизнесе в первую очередь, какая будет окупаемость, и нужен ли вообще AI для вашей задачи (иногда — нет).

Или просто напишите свой вопрос — отвечу в течение 2 часов