Перейти к содержимому

Разрешить сайту считать ваши посещения с помощью Яндекс Метрики? Для этого она сохранит в браузере файлы cookie. Как сайт использует cookie

VC
Кейс 9 из 22 · Интернет-торговля · аналитика

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

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

Отрасль
Интернет-торговля · два магазина на Shopify
Технологии
Python · Shopify Admin API · Google Sheets API · systemd
Сроки
Разовая сверка — 1 день, ежедневная проверка — неделя
Итог
разрыв 8,4% объяснён, сверка идёт каждый день
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, ни один не потерялся ни с одной стороны.

ИИ-агенты нашли в свежем коде 11 дефектов

Вскоре после запуска модуль проверили ИИ-агенты, у которых была одна задача: найти, что в нём неверно. Итог — 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 APIJSONsystemdpytestПроверка ИИ-агентами
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% денег. Если охват ниже, заключения нет, и на экране стоит «не сверено». Если Shopify не ответил, это показывается как сбой. Если сравнивать не с чем, процент не считается и на экране стоит прочерк.

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

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

Где ещё работает тот же подход

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

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

Три отчёта дают три разные выручки? Их можно свести до конкретного заказа

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

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

Начните с аудита за 5 000 ₽: письменный отчёт и расчёт окупаемости

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

Или просто задайте вопрос. В рабочее время отвечаю в течение 2 часов