Автоматизированный финансовый учет и контроль рентабельности
Автоматический P&L, потоварная рентабельность по каждому SKU и анализ стоимости хранения. Один инструмент вместо десяти Excel-файлов.
Знакомо?
WB удерживает логистику, хранение, штрафы, рекламу… В итоге выручка есть, а прибыли нет. Вы не видите реальный P&L и не понимаете, зарабатываете ли вообще.
Без потоварного учета по каждому SKU невозможно понять, какой товар приносит прибыль, а какой — убыток. Штрафы и хранение «размазаны» по всему бизнесу.
Скачать 5 отчётов из ЛК, разархивировать, объединить в Excel, вручную сопоставить... И так каждый понедельник. Потерянное время — потерянные деньги.
Тарифы WB за хранение растут. Но без расчёта стоимости хранения vs стоимости вывоза по каждому складу и SKU — решение принимается вслепую.
Один инструмент — полная картина бизнеса
WBTool подключается к 7 API Wildberries, загружает все данные и автоматически строит три ключевых отчёта.
Полный P&L вашего бизнеса на WB:
- Выручка → Маржинальная прибыль → Операционный ФР → Чистый ФР
- 38 строк финансовых показателей
- Детализация: по месяцам / неделям / дням
- Автоматический расчёт УСН, ROI%, маржинальности
Потоварная рентабельность каждого SKU:
- Продажи, возвраты, комиссия WB, логистика
- Себестоимость, реклама, хранение, штрафы
- Маржа, ROI%, средняя цена продажи
- Остатки на складах WB в реальном времени
- Фото товаров в отчёте
Калькулятор рентабельности хранения:
- Стоимость хранения за 30 дней по каждому складу WB
- Стоимость вывоза/возврата по актуальным тарифам
- Себестоимость замороженных остатков
- Фото товаров в отчёте
Что загружается автоматически
Одна кнопка «🔄 Актуализировать данные» — и все 8 модулей загрузятся в фоне. Можно закрыть таблицу.
| Модуль | Данные | API |
|---|---|---|
| Финансовые отчёты | Еженедельные + ежедневные детализации реализации | finance-api |
| Цены и скидки | Базовые цены, скидки, СПП по каждому SKU | discounts-prices-api |
| Остатки FBW | Остатки по всем складам WB + транзит | seller-analytics-api |
| Поставки | Полная история отгрузок с детализацией по ШК | supplies-api |
| Реклама | Расходы, клики, показы по кампаниям и SKU | advert-api |
| Карточки товаров | SKU, баркоды, артикулы, габариты | content-api |
| Хранение | Ежедневная стоимость хранения по баркодам | analytics-api |
| Платная приёмка | Расходы на приёмку товаров | analytics-api |
📂 Загрузка из Excel
Разархивируйте отчёты из ЛК на Google Диск — WBTool сам объединит их
📋 Номенклатура
Справочник товаров с себестоимостью и привязкой по штрих-кодам
🗂️ Группировка SKU
Объединяйте товары в категории для агрегированной аналитики
Настройка за 5 минут
Скопируйте таблицу
Нажмите «Файл → Создать копию». Дождитесь появления меню WBTool.
Нажмите «Сгенерировать чистый Ввод_Данных»
При первом запуске дайте скрипту права доступа — это стандартная процедура Google.
Настройте WB API Token
Создайте персональный токен в ЛК Wildberries с правами: Контент, Аналитика, Продвижение, Финансы, Поставки, Цены.
Загрузите отчёты
Через API (рекомендуется) или из файлов на Google Диске.
Заполните себестоимость
Вручную или автоматически из справочника «Номенклатура».
Получите результат
Нажмите «Рассчитать ЧФР» или «Рассчитать Аналитику SKU» — готово!
Проект в цифрах
Частые вопросы
Это бесплатно?
Мои данные в безопасности?
Скрипт говорит «Время вышло, нажмите ещё раз» — что делать?
Можно ли использовать для нескольких магазинов?
Чем это лучше платных сервисов?
Перестаньте считать вручную
Скопируйте таблицу, подключите API-токен — и WBTool соберет полную историю продаж в фоновом режиме. Первичная загрузка крупных магазинов может занять время, но затем все отчеты будут обновляться в один клик.
🎯 Получить WBTool бесплатноGoogle Таблица • Без установки • Без подписки • Без серверов
Этот раздел — для разработчиков, Tech Lead'ов и HR. Ниже — технический разбор архитектуры, паттернов и инженерных решений проекта.
Обзор проекта
Stack: Google Apps Script (V8 Runtime) Core: LibraryScript.js — 8 800+ LOC, 110 functions Client Wrapper: Code.js — 82 LOC APIs integrated: 7 (Wildberries) + Sheets API v4 + Drive API Architecture: Library Pattern + State Machine Orchestrator Deployment: clasp CLI → obfuscated build → Google Cloud
Ключевые характеристики:
- Полностью serverless — работает в облаке Google, zero-cost infrastructure
- Обфускация ядра для защиты IP (JavaScript Obfuscator)
- CI/CD через clasp CLI:
dev:push:lib/prod:pushпайплайны - 17 листов генерируются и форматируются программно
Архитектурные паттерны
Wrapper + Core (Code.js → LibraryScript.js)
+-----------------------------------------------------+
| Client Spreadsheet (Code.js - 82 LOC) |
| |
| onOpen(e) -> WBToolLibrary.buildMenu() |
| |
| menuAction1() --+ |
| menuAction2() --+ |
| ... --+--> _run(slot) |
| menuAction25() --+ | |
| v |
| try { WBToolLibrary |
| .dispatchMenuAction(slot) } |
| catch(e) { _showError(e) } |
+-----------------------+-----------------------------+
| Library Bridge |
+-----------------------v-----------------------------+
| WBToolLibrary (LibraryScript.js - 8800+ LOC) |
| |
| dispatchMenuAction(slot) { |
| switch(slot) { |
| case 1: return startReportMerging(); |
| case 7: return calculateCFR(); |
| case 18: return actualizeSkuData(); |
| ... |
| } |
| } |
+-----------------------------------------------------+
Hot-swap обновления: Обновление ядра для всех пользователей — один
clasp push. Клиентский код не меняется.Dynamic Dispatch: Клиенту не нужно знать, что выполняет
menuAction7().
Маршрутизация жёстко прописана в ядре.
State Machine Orchestrator (обход 6-минутного лимита)
Google Apps Script убивает любой скрипт через 6 минут. WBTool загружает данные из 8 API-эндпоинтов, что занимает 15–40 минут. Решение — Finite State Machine на базе минутных триггеров.
+-----------------------------------------------------+
| actualizeSkuData(isBackground) |
| |
| State = PropertiesService.get("WB_ACTUALIZE_STATE")|
| { |
| "currentStep": 3, // 0..7 |
| "dateTo": "2024-05-31", |
| "startTime": 1717144800 // stale session guard |
| } |
| |
| while (state.currentStep <= 7) { |
| if (elapsed > 250s) { // <- 4.1 min guard |
| saveState(); |
| return; // exit gracefully, trigger continues |
| } |
| executeStep(state.currentStep); |
| state.currentStep++; |
| } |
| |
| deleteAllTriggers(); |
| showSuccess("✅ Завершено"); |
+-----------------------------------------------------+
^ |
| every 1 min | on first call
| v
+----+----------------------------------+
| ScriptApp.newTrigger('menuAction25') |
| .timeBased() |
| .everyMinutes(1) |
| .create(); |
+---------------------------------------+
Механика:
- Пользователь нажимает «🔄 Актуализировать» → запускается Step 0
- Оркестратор создаёт ежеминутный фоновый триггер
- Каждую минуту триггер «будит» оркестратор с сохранённого шага
- При превышении 250 секунд — graceful exit + сохранение JSON-состояния
- На финальном шаге триггер удаляется, статус → «✅ Завершено»
- Пользователь может закрыть таблицу — процесс продолжится в облаке
WB_ACTUALIZE_ERROR_COUNT — до 3 попыток на
шаг. Между попытками — минутный интервал (Exponential Backoff на уровне инфраструктуры). При 3 фейлах —
cleanup всех триггеров, статус «❌ Ошибка». Stale session guard: если процесс завис >12 часов →
автоматический сброс.
Работа с API Wildberries
Rate Limiting & Retry Strategy
+-------------------------------------------------+
| _handleApiResponse(response, apiName) |
| |
| HTTP 200-299 -> JSON.parse(body) |
| +- catch: "API вернуло невалидный JSON" |
| |
| HTTP 401/403 -> context-aware error |
| +- apiName.includes('promotion') |
| ? "Нужны права «Продвижение»" |
| : "Проверьте токен WB" |
| |
| HTTP 429 -> throw Error (NOT sleep!) |
| +- Перехватывается Оркестратором |
| -> increment error counter |
| -> exit session |
| -> retry in 1 min via trigger |
| |
| HTTP 5xx -> throw "Сервер WB недоступен" |
+-------------------------------------------------+
Utilities.sleep(30000). Но в среде GAS это сжигает ценные секунды из
6-минутной квоты. Архитектура WBTool выбрасывает ошибку наверх, позволяя оркестратору завершить сеанс и
переложить ожидание на инфраструктуру Google.
Исключение — Supplies API (Поставки)
Этот API требует сотни последовательных GET-запросов. Здесь используется динамический парсинг HTTP-заголовков:
if (responseCode === 429) { var headers = response.getHeaders(); var retryAfter = headers['retry-after'] || headers['x-ratelimit-retry']; var waitMs = retryAfter ? (parseInt(retryAfter, 10) + 1) * 1000 : 5000; Utilities.sleep(waitMs); // точное время бана от WB }
Оптимизация производительности
Batch-операции с Sheets API v4
Форматирование P&L-отчёта (38 строк × 50+ колонок) через стандартный
getRange().setBackground() занимает ~30 секунд. WBTool использует
Advanced Sheets API v4 BatchUpdate:
// Один запрос вместо сотен
var requests = [];
requests.push({ updateSheetProperties: { ... } });
requests.push({ repeatCell: { range: {...}, cell: { format: { backgroundColor: ... } } } });
// ... 50+ операций форматирования
Sheets.Spreadsheets.batchUpdate({ requests: requests }, spreadsheetId);
// Время: ~0.5 секунды
High-Performance XLSX Parser
Стандартная конвертация Excel→Google Sheets через Drive API: 30–60 секунд на файл. WBTool парсит XLSX напрямую в памяти как ZIP-архив:
blob.setContentType('application/zip');
var xmlFiles = Utilities.unzip(blob);
// Парсинг xl/sharedStrings.xml через String.split(' тегов
Безопасность и защита данных
| Аспект | Реализация |
|---|---|
| Хранение токена | PropertiesService.getDocumentProperties() — не в ячейках, не в коде |
| Передача копии | Токен НЕ копируется при «Файл → Создать копию» |
| Обфускация ядра | JavaScript Obfuscator → обфусцированный билд в продакшн-библиотеку |
| Права токена | Только «Чтение» — скрипт не модифицирует данные в ЛК WB |
| Graceful Error Handling | Интерактивный режим → UI Alert; Фоновый режим → console.error |
Технологии и инструменты
Ключевые инженерные решения
| Проблема | Решение | Результат |
|---|---|---|
| 6-минутный лимит GAS | State Machine + минутные триггеры | Загрузка 8 API без ограничений |
| Rate Limit 429 от WB | Throw → Orchestrator retry (не sleep) | Не сжигает квоту GAS |
| Медленное форматирование | Sheets API v4 BatchUpdate | 3 мин → 0.5 сек (x360) |
| Медленный парсинг XLSX | ZIP-распаковка + String.split XML | 60 сек → 5 сек (x12) |
| Квота на Sheets API calls | In-memory batch preload всех листов | Сотни вызовов → 1 пакетный |
| Защита бизнес-логики | Library Pattern + JS Obfuscator | 25 пустых слотов |
| Безопасность токена | DocumentProperties (не ячейки) | Токен не утекает при копировании |
| Изменчивость API WB | Column mapping + fallback synonyms | Устойчивость к переименованиям |
| Фоновый режим без UI | Dynamic status bar на листе (F5:J5) | Цветная плашка прогресса |
| Зоопарк форматов дат | Universal date parser | RU-локаль + ISO + Excel serial |