Задача
Продавец на Wildberries раз в неделю получает отчёт о реализации: XLSX на 84 колонки и до сотен тысяч строк. В кабинете видна сумма к перечислению, но не видно, сколько принёс каждый товар после закупки. Обычно это считают вручную в Excel, а готовые сервисы просят API-ключ от кабинета.
Решение
Стат.Свод считает прибыль по каждому товару прямо из этого отчёта:
- продавец перетаскивает файл, и браузер разбирает его на месте. Отчёт никуда не отправляется;
- справочник себестоимости хранится между отчётами и учитывает даты: если закупочная цена поменялась посреди недели, каждая продажа считается по своей;
- на дашборде прибыль по товарам, путь от выручки к прибыли, ABC-анализ и выгрузка в Excel;
- итог сверяется с отчётом до копейки тремя независимыми способами, и любое расхождение сразу видно.
API-ключи не нужны. В этом главное отличие от конкурентов.
Технические решения
Свой потоковый парсер XLSX. Популярные библиотеки читают файл в память целиком, а лист на 400 тыс. строк в распакованном виде весит около гигабайта. Парсер читает zip по центральному каталогу, распаковывает его штатным DecompressionStream и разбирает лист потоком в Web Worker. Таблица общих строк целиком в память не попадает: ключи товаров остаются номерами до конца разбора. 400 тыс. строк обрабатываются за 4,5 секунды. Память зависит от числа товаров, а не от размера файла: каталог на 5000 товаров укладывается в 100 МБ.
Деньги в целых копейках. На сотнях тысяч слагаемых дробные числа копят погрешность, и сверка до копейки перестала бы сходиться.
Сквозное шифрование себестоимости. Закупочные цены — коммерческая тайна, сервер не должен их видеть. Браузер выводит из пароля два ключа (PBKDF2 на 600 000 итераций, затем HKDF). Ключ шифрования остаётся в браузере, на сервер уходит только доказательство входа, и хранится оно там как scrypt-хеш. Справочник сжимается и шифруется AES-GCM, а открытые поля подписаны вместе с шифротекстом, чтобы их нельзя было подменить. Даже полная утечка базы не раскрывает ни одной цены. Цена такого решения: забытый пароль восстановить нельзя.
Минимум зависимостей. Разбор XLSX и zip, шифрование и запись Excel сделаны на штатных API браузера, без сторонних библиотек и wasm. Сервер на Node 24 запускает TypeScript напрямую, без сборки, а база — встроенный node:sqlite.
Тесты на реальных объёмах. Генератор синтетических отчётов на 1 тыс., 100 тыс. и 400 тыс. строк с заранее посчитанными итогами, бенчмарк парсера и около 490 тестов на Vitest.
Моя роль
Сделал всё один, от идеи до запуска: продукт, архитектуру, фронтенд, бэкенд и инфраструктуру. Сервер работает на VPS за nginx, резервные копии лежат в S3 в другом городе.
statsvod.ru