VC LABКейсыКейс: аналитика возвратов

Аналитика возвратов: где товар не продаётся

Поставщик отгружает товар в федеральные розничные сети и получает обратно списания — каждая сеть в своём формате: Excel-выгрузки, PDF-уведомления о возврате, сканы и фотографии документов. Учёт вёлся вручную в десятке таблиц, процент возврата по точкам никто не считал. Нужна была система, которая сама собирает данные из разнородных источников и показывает, где товар не продаётся.

Что внутри

  • Адаптеры под каждого контрагента. Форматы отчётов различаются принципиально — дневная детализация у одной сети, недельный pivot у другой. Тип файла определяется по содержимому, а не по имени.
  • Конвейер распознавания PDF. Цифровые документы читаются текстовым слоем, сканы уходят в OCR с автоподбором поворота, спорные случаи дочитываются зрением модели. Многостраничные файлы разбираются полистно с выбором нужного документа среди накладных, форм урегулирования и подписных листов.
  • Защита от ложных данных. Сумма позиций сверяется с итогом из документа. Не сошлось — запись блокируется и документ уходит на ручную проверку, вместо того чтобы молча занести выдуманные цифры.
  • Обратимость операций. Каждая загрузка хранит снимок состояния до и после; любую можно исключить из расчётов и вернуть обратно, не теряя остальные данные.
  • Аналитика. Процент возврата по связке «магазин × товар», drill-down от сети к точке и позиции, суммы в деньгах и штуках, контроль полноты загруженных данных, отчёт по позициям с высокими потерями.

Контроль качества

Разработка шла в режиме «правка — тест — живая проверка — деплой». Каждое изменение закрывалось автотестом, визуальные правки проверялись в браузере.

  • 376 автотестов на pytest: бизнес-логика, парсеры, API.
  • 12 браузерных тестов, которые исполняют реальный код фронтенда в изолированном окружении с подменённым DOM.
  • Трёхуровневая изоляция тестовой базы, исключающая запись в боевые данные.
  • Проверка целостности после каждого деплоя: контрольные суммы файлов, ответы всех эндпоинтов, сверка показателей до и после.

Отдельный класс дефектов ловился только живой проверкой: каскадные конфликты CSS, замороженные анимации, элементы, которые присутствуют в DOM, но не видны на экране.

Стек

  • Бэкенд: Python 3, FastAPI, SQLAlchemy, SQLite с заделом под PostgreSQL, Uvicorn.
  • Обработка данных: pandas, openpyxl, ETL-конвейер с идемпотентной загрузкой.
  • Распознавание документов: pdfplumber, PyMuPDF, Tesseract OCR, Claude Vision API.
  • Фронтенд: vanilla JavaScript, Jinja2, CSS без фреймворков и сборки.
  • Тестирование: pytest, Node.js и vm для DOM-тестов.
  • Инфраструктура: systemd, rsync-деплой, basic-auth, снапшоты с откатом.

Результат

  • Ручной сбор данных заменён автоматической загрузкой из всех источников.
  • Процент возврата считается по каждой торговой точке и позиции.
  • Доля документов, требующих ручного ввода, снижена в четыре раза за счёт доработки конвейера распознавания.

Частые вопросы

Как система понимает, какой это файл?
По содержимому, а не по имени: у каждой сети свой адаптер, а формат определяется по структуре — дневная детализация у одной сети, недельный pivot у другой.
Что происходит, если распознавание ошиблось?
Сумма позиций сверяется с итогом документа. При расхождении запись блокируется и документ уходит на ручную проверку, а не попадает в расчёты с выдуманными цифрами.
Можно ли отменить неудачную загрузку?
Да: каждая загрузка хранит снимок до и после, её можно исключить из расчётов и вернуть обратно без потери остальных данных.
Зачем браузерные тесты, если есть 376 автотестов на pytest?
Часть дефектов видна только на экране: каскадные конфликты CSS, замороженные анимации, элементы, которые есть в DOM, но не видны. Их ловят живая проверка и 12 тестов, исполняющих реальный код фронтенда.

Расскажите о задаче

Ответим в течение одного рабочего дня, оценку пришлём за 1–2 дня. Бесплатно.

Обновлено: 2026-10-02