Привет! Меня зовут Алексей Одиноков, я продаю сезонные товары на Озон. В этой статье хочу поделиться тем, как мы создали инструмент на основе google sheets для контроля товарных остатков на складе Озон по схеме работы FBO (fulfillment by Озон). Я расскажу, как таблица помогает автоматизировать принятия решений по поставкам товара на склад Озон и ответить на такие вопросы как: 

  • когда начинать подготовку поставки товара на склад ? 

  • в каком объеме заказывать товар, чтобы избежать платного хранения на складе Озон ? 

  • как ежедневно отслеживать оборачиваемость и динамику продаж по каждому артикулу?

Эта статья будет Вам полезна, если Вы ищете способы оптимизации бизнес-процессов, связанных с планированием и контролем остатков товаров на складе Озон. 

Озон - популярная площадка не только для покупателей, но и для продавцов. На конец первого квартала 2022 года продавцов более 120 000. Все селлеры (это Озон так называет продавцов) хотят много денег и больших продаж. И Озон дает все необходимые инструменты, чтобы реализовать ваш товар. Но если про рекламу и продвижение товаров говорят много и подробно, то вот тему inventory management опускают на второй план. А судя по обсуждениям в соцсетях проблем вывоза излишков со склада и больших расходов на хранение товара тема довольно актуальная. К счастью, мы не вывозили товар со склада по причине плохих продаж, скорее наоборот, проблема была в своевременном пополнении запасов. Товар заканчивается, а новая партия еще не успела доехать и это была систематическая ошибка планирования поставок, в результате чего теряется прибыль. Другая проблема заключалась в выборе оптимального объема поставки. Отправляем мало - быстро заканчивается товар и опять не успеваем пополнить остатки вовремя. Отправляем много озон включает платное хранение, т.к показатели оборачиваемости превышают границу в 120 дней. Приходится снижать цены и повышать расходы на рекламу, чтобы увеличить оборачиваемость. В итоге вся работа сводилась к балансу между этими двумя крайностями. Чтобы найти эффективное решение мы рассмотрели много инструментов, но в итоге пришли к самому простому (и дешевому надо сказать) - google-таблица и скрипт для сбора информации. 

Выбор FBO или FBS

Озон предлагает 2 схемы работы: FBO (fulfillment by Озон) - отгрузка со склада Озон и FBS (fulfillment by seller) - отгрузка со склада продавца. FBS подразумевает, что все операции связанные с хранением, упаковкой и доставкой товара в сортировочный центр лежат на продавце. В этом варианте есть очевидные плюсы в том, что никто не контролирует твою оборачиваемость и не включает счетчик, когда товар “залежался” на складе. Поэтому продавцы, особенно те у кого широкий ассортимент любят эту схему за то, что можно разместить тысячи артикулов и отвозить только то что продается, а что “залежалось” продавать в других каналах. Мы работаем по этой схеме с самого начала. Весь товароучет ведем в 1с, а интеграция с API Озон позволяет проводить все необходимые операции с остатками: резервировать, когда приходит заказ и передавать свободный остаток на озон по расписанию. И собственно вся работа со стоком понятна. 1с из коробки справляется со всеми задачами. Общая схема выглядит следующим образом.

приход товара -> общий сток -> выгрузка остатков на озон -> заказ с Озон -> резервирование товара -> формирование ежедневной отгрузки -> реализация. 

Все процессы, связанные с товаром проходят через программу. По динамике ежедневных продаж понятна оборачиваемость каждого артикула, сезонные коэффициенты спроса и уже исходя из этого можно планировать закупочную деятельность: находить точку повторного заказа (reorder point) и определять объем заказа. Немного расскажу про эти 2 параметра, которые связаны между собой. 

Как найти точку заказа?

Эффективность работы склада определяется оборачиваемостью товаров, т.е чем меньше времени товар лежит на складе, тем эффективнее используется склад. Но следствием высокой оборачиваемости является быстрое истощение запасов. Чтобы вовремя пополнять запасы необходимо знать точку повторного заказа. Это количество товарных остатков, которое покрывает прогнозируемый спрос на время, которое требуется для пополнения запасов. Так вот идеальная точка заказа дает достаточно времени, чтобы сделать новый заказ до того, как остатки достигнут критически низкого уровня. Чтобы найти эту точку нужно умножить средний объем продаж в  день на среднее время выполнения заказа и прибавить уровень страхового запаса.  Страховой запас определяем по следующей формуле: (максимальный объем продаж за день (шт) x максимальное время выполнения заказа в днях) – (средний объем продаж за день x среднее время выполнения заказа в днях). Страховой запас помогает снизить влияние всплесков повышенного спроса или нехватки товара у поставщика. Таким образом идеальная точка повторного заказа, как правило, немного выше уровня страхового запаса с учетом времени доставки. Пример идеального графика пополнения остатков представлен на рисунке ниже.

График изменения остатков товара на складе
График изменения остатков товара на складе

Приведу пример. У нас есть артикул со средним уровнем ежедневной реализации около 12 шт., в максимуме в сезон бывает и 20 шт. в день. Время выполнения заказа (т.е. время от отправки заявки поставщику до получения товара на склад) в среднем составляет 4 дня. Самое долгое время ожидание 7 дней. Уровень страхового запаса считаем так (safety stock) ss = 20 х 7 - 12 х 4 = 92 шт. Тогда точка повторного заказа (reorder point) rop = 12 x 4 + 92 = 140. То есть когда остатки снижаются до количества в 140 шт. необходимо делать заказ поставщику. Естественно время выполнения заказа и среднесуточный объем продаж не постоянные величины, и они имеют свойство меняться и колебаться, поэтому здесь лучше постоянно отслеживать эти метрики и держать под рукой.

Следующий вопрос какой объем товара заказывать? Здесь конечно может быть много нюансов, которые влияют на принятие решения об объеме партии это и требования поставщика по минимальному заказу и скидки от объема. Но если руководствоваться текущей ситуацией по оборачиваемости товара, то новая партия должна покрывать спрос на время необходимое, чтобы восполнить запасы, т.е. на среднее время выполнения заказа. В нашем примере заказ артикула будет такой (order quality) oq = 12 х 4 = 48 шт. Округляем кратно упаковкам товара и делаем заказ. Получается такая логика: исходя из текущего спроса и времени выполнения заказа мы определяем точку заказа и объем поставки. Если меняется одна из переменных, то соответственно меняются оба параметра. Эти несложные расчеты легко реализуются в 1с и проблем с своевременным пополнением остатков у нас не возникало.

С FBS разобрались. А что с FBO ?

Другое дело продавать со склада Озон. Время доставки товара от поставщика до склада Озон увеличилось в 2 раза. Если раньше от заказа до продажи было 4 дня, то теперь +2 дня на подготовку товара (штрих кодирование, упаковка), +8 дней доставка по кросс-докингу до склада Озон. Итого 14 дней. И если прибавить к этому увеличение оборачиваемости товара на 30% становится понятно, что необходимо пересчитывать точку заказа (ROP) и объем поставок (OQ). Также нужно иметь ввиду параметры платного хранения при определении объема поставки, чтобы не добавить себе дополнительных расходов на обслуживание стока. Порог оборачиваемости на складе Озон для большинства категорий 120 дней. Считают так: средний объем остатков за 14 дней (складывают актуальные остатки за 14 дней и делят на 14) делят на среднесуточный объем продаж (складывают все продажи за 14 дней и делят на 14) и получают прогноз по оборачиваемости. Если этот прогноз больше 120 дней включают счетчик согласно тарифу. 

Проблема заключалась в том, что теперь товародвижение на стороне Озон, поэтому стало сложнее следить за ежедневными остатками и динамикой продаж в разрезе каждого артикула и, как следствие, определять точку заказа. Вот и получалось так, что товара, который продавался по 15-20 шт. в день, не было от 3-х до 7 дней после распродажи всего остатка. Собственно поиск решения этой проблемы сводился к поиску нужного инструмента, который бы удовлетворял нашим требованиям:

  • Наглядное отображение сводной информации по артикулам, остаткам, количеству проданных товаров за период;

  • Свободный доступ к инструменту с любого устройства у всех членов команды;

  • Автоматизированный сбор данных по расписанию;

  • Гибкость. Чтобы была возможность настраивать условия для отображения нужных данных;

  • Возможность визуализации;

  • Безопасность хранения данных.

Готовые решения предлагают все и сразу от учетной системы до рекламных инструментов, интеграции со всеми маркетплейсами и все это, естественно, на платном тарифе. Переезжать на другую учетную систему нам не хотелось, а вариант доработки расширения для 1с оказался затратным и длительным по времени. Поэтому мы решили создать свой инструмент исходя из задачи и требований и, как нельзя лучше для этого подходит google sheets и google apps script на безе JavaScript. После недели работы с кодом и формулами удалось создать таблицу, которая решала нашу проблему. А условное форматирование помогло подсветить данные, которые требовали нашего внимания. Вот так выглядит таблица в итоговом варианте.

Google-таблица с данными по остатками и оборачиваемости товаров
Google-таблица с данными по остатками и оборачиваемости товаров

Сразу скажу, что в конце статьи будет ссылка на шаблон. Вы можете скопировать и примерить это решение для себя. Но для полного понимания логики работы таблицы ниже я приведу небольшой гайд, что из чего вытекает, чтобы на каком-то шаге Вы могли изменить структуру и настройки под себя. Поехали.

Создаем таблицу

Вот список листов, которые мы создадим:

  • stock - это главный лист на него будем стягивать все данные;

  • справочник - это список товаров с артикулами и Id;

  • metrics - на этот лист выгружаем данные аналитики;

  • historyOrdered - на этот лист будем сохранять ежедневно данные по главной метрике для отслеживания динамики.

Сначала создаем лист “справочник” на этот лист добавляем информацию об идентификаторах товара (FBO Озон SKU ID, FBS Озон SKU ID, артикул, наименование (если нужно)). С этого листа будем брать нужную строку функцией ВПР. Все данные можно взять в личном кабинете Озон. Здесь данные статичные, поэтому когда добавите новый товар, то, нужно вручную добавить новую строку по товару в справочник.

В итоге вот что получается. Сохраните тот же порядок столбцов. 

После справочника создаем главный лист “stock” (если даете свое имя не забудьте поменять его в коде скрипта). Сюда будем подгружать все данные. Создаем структуру таблицы, определяем названия столбцов. В моем случае это: 

Здесь

№ - это порядковый номер товара по возрастанию в том порядке в которым они хранятся в базе на озон.

Наименование товара не использую в своей таблице, т.к. ориентируюсь по артикулу. Но думаю, если кому надо будет добавить этот столбец, то сделать это не сложно. Главное добавляйте его слева артикула, чтобы сохранить диапазон выгрузки значений. 

Артикул (sku) - это ваш код товара.

Кол-во FBO, FBS - количество товара, доступное для продажи (общее количество товара минус зарезервированное количество товара) на складе Озон (FBO) и своем складе (FBS).

Заказано за 14 дней - это количество товара в шт, которое заказали за предыдущие к актуальной дате 14 дней. Почему 14? Это время выполнения заказа (в скрипте это переменная period. Можно задать свой период выгрузки данных). Это время от момента отправки заявки поставщику до оприходования товара на складе Озон.  Динамику этой метрики мы будем отслеживать и ежедневно сохранять на другой лист (далее расскажу подробнее).

Среднесуточный объем заказов - это количество заказанных товаров за 14 дней деленное на 14 или F2/14.

Прогноз оборачиваемости FBO - это прогнозируемое количество дней, необходимое для продажи всего остатка по артикулу (формула D2/G2).

Возвраты - это количество возвращенных единиц товара за 14 дней.

Динамика заказов - это спарклайн (мини график) изменения метрики количества заказанного товара за 14 дней.

Далее пишем первую часть скрипта для выгрузки данных о количестве товаров на складах. Для начала копируем client Id и создаем API Key с доступом администратор из личного кабинета Озон в разделе настройки.

Создаем скрипт. Кто не знает идем в меню расширения -> Apps script. Выбираем файл с расширением .gs и даём ему понятное имя. Переходим в содержимое файла. Удаляем все, что там есть и вставляем код ниже, только меняем client id и API key на свой.

//Прописываем константы
//Заполняем своим ключом apiKey и clientId из личного кабинете Озон
const apiKey = 'd6cd4a48-88cb-44ad-8c1a-cd2666084d1a'; 
const clientId = '24759';
const headers = {
        'Client-Id': clientId,
        'Api-Key': apiKey
      };
//Тело запроса на получение остатков товара
var body = {
      "filter": {
        "visibility": "ALL"
      },
      "limit": 500 // Если товаров больше 500 меняем на нужное количество. Ограничение: Минимум — 1, максимум — 1000.
    };
//Параметры запроса
var options = {
    "method": "POST",
    "headers": headers,
    "contentType": "application/json",
    "payload": JSON.stringify(body)
    };

//Меню в интерфейсе таблиц 
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu('Ozon')
      .addItem("Получить остатки", "displayStock")
      .addSeparator()
      .addItem("Получить метрики", "displayMetrics")
      .addToUi()
}

//Функция-запрос к API Ozon. Метод: "Информация о количестве товаров". Возвращает информацию о количестве товаров по FBS и FBO
function callRequestOzonStock() {
  var response = UrlFetchApp.fetch("https://api-seller.ozon.ru/v3/product/info/stocks", options);
  // Parse the JSON reply
  var json = response.getContentText();
  var data = JSON.parse(json);
  return data;
}

//Отображаем на листе нужную нам информацию о количестве товаров.
function displayStock() {
  //Активируем таблицу
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('stock'); //берем лист с именем stock
  //Берем из ответа нужный фрагмент и далее из него вытаскиваем данные
  var result_stock = callRequestOzonStock().result.items;
  
  //создаем контейнер куда будем помещать наши данные
  var output_stock = [];
  let i = 1;
//Перебираем каждый элемент и из него вытаскиваем нужное (артикул, остаток FBS, остаток FBO) и отправляем в output_stock
  result_stock.forEach(function(elem) {
    var sku = elem.offer_id;
    var stock_fbo = elem.stocks.filter(x => x['type'] == 'fbo').map(y => y.present - y.reserved);
    var stock_fbs = elem.stocks.filter(x => x['type'] == 'fbs').map(y => y.present - y.reserved);
    output_stock.push([i++, sku, stock_fbo, stock_fbs]);
  })

  var len = output_stock.length;
  //Перед выводом сортируем таблицу по номеру (№). Это нужно, чтобы сохранялась разметка таблицы
  sheet.sort(1);
  sheet.getRange(2,1,500,4).clearContent(); //стираем таблицу
  sheet.getRange(2,1,len,4).setValues(output_stock); //вставляем данные на лист stock
  //Центрируем по вертикали и горизонтали
  sheet.getRange(2,1,500,7).setVerticalAlignment("middle");
  sheet.getRange(2,1,500,7).setHorizontalAlignment("center");
  ss.toast('Остатки выгружены');
}

Сохраняем скрипт и запускаем (даем все права, которые спросит Google). Смотрим таблицу.

Отлично. Теперь у нас есть таблица с остатками по каждому артикулу. Обратите внимание, что в меню сверху появилась кнопка Озон (если не появилась перезагрузите таблицу). Теперь скрипт можно запустить через эту кнопку в интерфейсе. 

Дальше нужно добавить аналитические данные в нашу таблицу. За это отвечает другой метод Seller API, который называется “данные аналитики” (ссылка). Можно запрашивать разные метрики: количество показов, сессии, конверсии, выручку, возвраты и количество заказов. Это я к тому, что запрашивать зависит от вашей цели, но при желании можно сделать целый аналитический дашборд с показателями. В рамках нашей задачи нам нужны показатели заказанных товаров и возвраты (ordered_units и returns). Перед тем, как перейти к написанию скрипта сначала создаем еще один лист, который назовем “metrics”. На этот лист будем выгружать данные. А уже на главный лист “stock” будем переносить формулой. Почему не сразу выгружать на лист stock ? Дело в том, что на Озон каждому артикулу соответствуют 2 карточки товара и соответственно уникальных идентификаторов id. Одна карточка для работы по схеме FBS, другая соответственно по FBO. Справочник мы делали именно за тем, чтобы каждому уникальному id присвоить артикул и наименование. Поэтому аналитические данные предоставляются в разрезе каждого id артикула. К примеру, у товара с артикулом sku1 будут данные по заказам за 14 дней со склада Озон 35 шт и со склада продавца (fbs) 10 шт. Мы эти данные по артикулу будем суммировать и переносить на главный лист "stock". На словах кажется запутанно, на деле все проще.

Создаем на листе metrics такие столбцы:

Скриптом будем выгружать данные в столбцы B:D.  А sku будем подгружать из справочника. Не даёт Озон данные по артикулу в этом запросе. Добавляем код на новую строку того же файла.

const period = 14; //указываем период до текущего дня за который придет отчет аналитики

//функция для возврата актуальной даты в нужном для запроса формате
function formatDateNow() {
  let nowDate = new Date(); //актуальная дата и время. Из нее вычитаем период
  let dd = nowDate.getDate();
  if (dd < 10) dd = '0' + dd;

  let mm = nowDate.getMonth() + 1;
  if (mm < 10) mm = '0' + mm;

  let yy = nowDate.getFullYear();
  let dt = yy + '-' + mm + '-' + dd;
  return dt
}
//функция для получения даты с которой начинается период для выгрузки аналитики
function offsetDate() {
  let nowDate = new Date();
  nowDate.setDate(nowDate.getDate() - period);
  let dd = nowDate.getDate();
  if (dd < 10) dd = '0' + dd;

  let mm = nowDate.getMonth() + 1;
  if (mm < 10) mm = '0' + mm;

  let yy = nowDate.getFullYear();
  let dt = yy + '-' + mm + '-' + dd;
  return dt
}

//функция запроса к API Ozon на получение аналитических данных по нашему магазину
function callRequestOzonMetrics() {
  var body = {
      "date_from": offsetDate(),
      "date_to": formatDateNow(),
      "metrics": [                //здесь определяем метрики, который будем выгружать (список метрик в документации)
        "ordered_units", 
        "returns"
    ],
    "dimension": [
        "sku"
    ],
    "sort": [
        {
            "key": "ordered_units",
            "order": "DESC"
        }
    ],
    "limit": 1000,
    "offset": 0
    };
//Параметры запроса
  var options = {
    "method": "POST",
    "headers": headers,
    "contentType": "application/json",
    "payload": JSON.stringify(body)
    };
  var response = UrlFetchApp.fetch("https://api-seller.ozon.ru/v1/analytics/data", options);
  var json = response.getContentText();
  var data = JSON.parse(json);
  Logger.log(data.result.data);
  return data;
}

//функция выгрузки данных в таблицу
function displayMetrics() {
  //Активируем таблицу
  var ss = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = ss.getSheetByName('metrics'); //активируем лист metrics
  //Берем из ответа нужный фрагмент и из него вытаскиваем нужную инфу
  var resultMetrics = callRequestOzonMetrics().result.data;
  var outputMetrics = []; //создаем контейнер куда будем складывать данные
  
  resultMetrics.forEach(function(elem) {
    var nameId = elem.dimensions[0].id;
    var metricsOrdered = elem.metrics[0];
    var metricReturn = elem.metrics[1];
    outputMetrics.push([nameId, metricsOrdered, metricReturn]);
  })

  len = outputMetrics.length; //находим длину массива
  sheet.getRange(2,2,500,4).clearContent(); //Перед выводом стираем таблицу
  sheet.getRange(2,2,len,3).setValues(outputMetrics); //добавляем данные в таблицу
 
  //Центрируем по вертикали и горизонтали
  sheet.getRange(2,2,500,7).setVerticalAlignment("middle");
  sheet.getRange(2,2,500,7).setHorizontalAlignment("center");
}

После запуска скрипта в таблице должны были появиться данные. Запуск скрипта также появился в меню Озон.

Теперь добавляем sku из справочника формулой:

Здесь fbo_id и fbs_id именованные диапазоны из справочника A:B и D:E соответственно. Теперь у нас есть данные по заказам и возвратам за 14 дней. Переносим их на лист stock формулой. Суммируем показатели по артикулу формулой СУММЕСЛИ. С возвратами проделываем тоже самое.

Дальше считаем среднесуточный объем заказов. Его можно рассчитать, как E2/14. Прогноз оборачиваемости FBO можно рассчитать по формуле С2/F2. Таблица принимает такой вид:

Далее можно настроить условное форматирование. Я в рамках нашей задачи настроил подсвечивание красным цветом ячейки в столбце С и, когда значение в этой ячейке будет меньше или равно значению в столбце “заказано за 14 дней”. Это сигнал, чтобы начать подготовку товара к отправке на склад. Подсвечивание в столбце G (прогноз оборачиваемости > 120) говорит о том, что нужно повысить оборачиваемость товаров, чтобы не допустить платного хранения.

В целом этого функционала уже достаточно, чтобы контролировать остатки на складе Озон и определять точку повторного заказа. А также видеть прогноз оборачиваемости по остатку с учетом текущего спроса. Но как я уже сказал в начале статьи мы продаем сезонные товары, а это значит, что спрос сильно меняется со временем и нужно знать на какой части кривой спроса мы находимся в нисходящем тренде или восходящем. Для того, чтобы отслеживать метрику в динамике напишем скрипт, который будет записывать показания метрики на отдельный лист таблицы. Создадим новый лист с наименованием “historyOrdered”. В первый столбец добавим список артикулов в порядке возрастания номера. Данные будут записываться в том же порядке. 

Список должен быть статичен. Если удалить какой-то артикул на Озон в архив, то список изменится и соответственно данные будут копироваться уже измененного списка товаров. Новые товары можно добавлять только в конец списка (не из архива), тогда вся структура не изменится и данные будут записываться корректно. 

Создаем новый файл (например, copy.gs) удаляем содержимое и вставляем код ниже: 

//функция берет данные из столбца "заказано за 14 дней" и вставляет в последнюю колонку на листе historyOrdered в том же порядке, что и на листе stocksPrice (важно сохранять порядок выгрузки по каждому артикулу)
function copyOrdered() {
  var ss = SpreadsheetApp.getActive(); //активируем таблицы
  ss.getSheetByName('stock').sort(1) //возвращаем список товаров в исходное состояние (по возрастанию номера) 
  var lastColumn = ss.getSheetByName('historyOrdered').getLastColumn(); //находим номер последнего стобца с данными
  var valuesOrdered = ss.getSheetByName('stock').getDataRange().getValues(); //берем все данные на странице stocksPrice
  valuesOrdered.shift(); //удаляем первую строку с наименованиями стобцов
  var today = new Date(); //к каждому запуску скрипта будем добавлять дату и время выполения 
  var options = {timeZone: 'Europe/Moscow'};
  var ordered = []; //создаем контейнер, куда будем добавлять данные
  valuesOrdered.map(row => { //перебираем каждую строку и берем данные с индексом (4) нужного столбца ("заказано за 14 дней")
    ordered.push([row[4]]);
  });
  ordered.unshift([today.toLocaleString('ru', options).replace(',', '')]); //добавляем дату и время к массиву ordered
  const len = ordered.length;
  ss.getSheetByName('historyOrdered').getRange(1,lastColumn + 1,len,1).setValues(ordered); //добавляем данные на лист historyOrdered
}

Запускаем скрипт. Проверяем, что все работает: 

Теперь автоматизируем запуск скрипта по триггерам. Переходим в меню apps script в раздел “триггеры”.

Создаем в конце дня 3 триггера по времени. С 22-00 до 23-00 запускаем функции displayStock и displayMetrics. C 23-00 до 00-00 запускаем функцию copyOrdered для записи метрики на лист historyOrdered. Здесь важно сохранить время выгрузки метрик и записи данных постоянным, чтобы сравнение по дням было верное.

Проверяем на следующий день таблицу. На листе historyOrdered должен появится столбец с данными по заказам. Теперь каждый день данные будут записываться в соседний столбец. Вот как это выглядит, когда накопятся данные за несколько дней:

Теперь можно отслеживать метрику (количество заказов за 14 дней) в динамике и принимать решения об объеме поставки исходя из тренда. Добавим мини-график (спарклайн) изменения метрики по каждому артикулу на лист stock. Причем зададим параметры графика, чтобы менялся цвет кривой в зависимости от тренда. Если последнее значение меньше среднего значения этой метрики за 5 дней, то линия будет красной, а если больше то зеленой. И сделаем ее серой, если метрика равна нулю. Вот что получится: 

Сортируем таблицу по количеству товара на FBO и посмотрим на итоговую таблицу.

Теперь есть представление о том, какая динамика заказов наблюдается в разрезе каждого артикула. Опираясь на эти данные можно корректировать рекламу и объемы поставок. Например, если динамика заказов стабильно отрицательная, то есть вероятность, что пик спроса на товар прошел и следует учитывать последние данные по заказам (в самой нижней точке) для того, чтобы снизить объемы поставок (по сравнению с пиком продаж). Если же наблюдается стабильный рост заказов, то делаем прогноз на то, что спрос еще увеличится и рассчитываем объем с запасом на 100 дней. То есть, если продажи достигли уровня 12 шт. в день, то при достижении точки заказа, мы готовим объем в 1200 шт. Следуя этим правилам мы полностью исключили фактор сезонности, что позволило нам вовремя пополнять запасы, когда идет резкий всплеск заказов и снижать объемы, когда спрос падает, чтобы не попасть на платное хранение.

Итог

Этой таблицей мы пользуемся регулярно. Она помогает контролировать запасы на складе, принимать решения по поставкам и отслеживать оборачиваемость усиливая ее рекламой, акциями и ценой. Конечно это решение не является универсальным, и оно имеет ряд ограничений, связанных с количеством запросов к API, объемом обрабатываемых данных и скоростью обработки (если у вас больше 1000 sku, то работа скрипта может занять некоторое время). Можно посмотреть все ограничения по ссылке. Также нужно иметь ввиду, что при добавлении новых товаров необходимо вручную переносить в справочник уникальный id. А запись данных в базу (на лист historyOrdered) строго привязана к списку артикулов, что исключает возможность удаления или восстановления товаров из архива.  

В заключении Вы можете скопировать себе шаблонную таблицу (ссылка) и попробовать это решение для себя. Все что нужно сделать, чтобы скрипт начал работать это заполнить переменные api-key и client-id. И заполнить справочник по своим товарам.

После этого запускаем скрипт. 

На этом все. Спасибо за внимание! С удовольствием отвечу на ваши вопросы, если они есть.  

Комментарии (3)


  1. AlexHighTower
    19.06.2022 09:24
    +1

    В конце на картинке apiKey и clientId замазаны, а в тексте идут целиком и судя по всему они реальные…


    1. shark14
      19.06.2022 15:52

      Да нет, там же видно, что у автора apiKey разные в коде и на скрине. Но все равно в таких случаях обычно принято в коде плейсхолдеры писать, чтобы вопросов не возникало.


    1. alexOdin Автор
      19.06.2022 20:21

      Спасибо за комментарий. Я просто оставил формат ключа и id)