Аналитика возвратов: где товар не продаётся
Поставщик отгружает товар в федеральные розничные сети и получает обратно списания — каждая сеть в своём формате: 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, снапшоты с откатом.
Результат
- Ручной сбор данных заменён автоматической загрузкой из всех источников.
- Процент возврата считается по каждой торговой точке и позиции.
- Доля документов, требующих ручного ввода, снижена в четыре раза за счёт доработки конвейера распознавания.
Частые вопросы
Как система понимает, какой это файл?
Что происходит, если распознавание ошиблось?
Можно ли отменить неудачную загрузку?
Зачем браузерные тесты, если есть 376 автотестов на pytest?
Расскажите о задаче
Ответим в течение одного рабочего дня, оценку пришлём за 1–2 дня. Бесплатно.