Проекты / сквозной анализ цепи поставок

Проект · Python, SQL, DuckDB, 1С, симуляция

Сквозной анализ цепи поставок

Когда товара нет на полке магазина, важно понять, где в цепочке «поставщик - склад - магазин» возникла проблема: от этого зависит, кто и что должен исправить. Расчёт восстанавливает движение товара по дням на всех этапах и для каждого дня дефицита в магазине называет причину.

Данные синтетические. Это симуляция сети магазинов электроники: 60 моделей смартфонов Apple, поставщик, 3 склада и 30 магазинов, 1 августа - 31 октября 2025 года, включая выход iPhone 17. Разбор использует только то, что есть в учётной системе: заказы поставщику, журнал движений и текущий остаток. Таблицы устроены как выгрузки из 1С: справочники со ссылками-GUID, журнал движений с видом движения «приход/расход», как в регистре накопления, и заказы поставщику с заказанным и подтверждённым количеством. В симуляцию специально заложены проблемы на каждом этапе, чтобы проверить, что разбор их находит. Названия моделей реальные, цены и объёмы условные.

Коротко
  • Задача. Дефицит в магазине может возникнуть на любом этапе: поставщик недопоставил, закупщик заказал мало, склад не довёз. Без разбора непонятно, кому и что исправлять.
  • Что сделано. Восстановлены остатки каждого склада и магазина на каждый день, а для каждого дня дефицита причина определяется по пяти простым правилам - от магазина вверх по цепочке.
  • Результат. Дефицит стоил сети около 308 млн ₽ - 5,4% продаж. 77% этих потерь - ошибки внутри сети, в закупе и распределении, которые можно исправить; остальное - нехватка товара у поставщика.

1. Как движется товар

Поставщикподтверждает заказ целиком или частично
3 складакаждый обслуживает свой регион
30 магазиновпродают покупателям

Учётная система хранит только текущий остаток и журнал движений. Остаток на каждый прошлый день восстанавливается «откатом» назад: из сегодняшнего остатка вычитаются все движения после нужного дня. Так получена полная история по каждому складу и магазину - она совпала с истинной из симуляции в 100% случаев.

Дефицит в магазине бывает двух видов: весь день без товара (3 685 «магазино-дней» за период) и товар закончился за день (6 957). Во втором случае часть покупателей приходит, когда товара уже нет.

Дни дефицита в магазинах по неделямЧисло «магазино-товаро-дней» за неделю, когда товара не было весь день или он закончился: один товар без остатка 6 дней - это 6. Строка склада - сумма по его магазинам; нажмите на склад, чтобы раскрыть магазины. Первая неделя неполная (3 дня).
Склад / магазин01.0804.0811.0818.0825.0801.0908.0915.0922.0929.0906.1013.1020.1027.10
51114176254277246272326433579462493439322
2910293134190187176226277437435371302169
227793133202216243297282333308289325250

2. Как определяется причина

Для каждого дня дефицита разбор идёт по цепочке вверх и останавливается на первом ответе «да». Статус модели - новинка или выводимая - не важен: если товар продаётся, его нужно закупать.

Дефицит в магазине
1Остатка склада накануне вечером хватало, чтобы довезти товар этому магазину?
даошибка распределениясклад не довёз товар
2В других магазинах этого склада товар лежит с запасом больше недели продаж?
даперекос распределениясклад развёз товар неравномерно
3Поставщик привёз весь последний заказ (или заказа не было)?
даошибка закупазаказали недостаточно
4В других регионах товар лежит с запасом больше двух недель продаж?
даперекос закупадефицитный товар неравномерно распределён между складами
дефицит у поставщикатовара не хватило на всех - это не ошибка сети

3. Где теряются деньги

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

Упущенные продажи по причинам, млн ₽Цвет - этап цепочки: распределение, закуп, поставщик. Яркая часть - дни без товара, приглушённая - дни, когда товар закончился.
Упущенные продажи по неделям, млн ₽Неделя - с понедельника. Рост в середине периода - перебои у поставщика, пик в конце сентября - старт продаж iPhone 17.

Старт продаж iPhone 17. Новинки продаются с 27 сентября, но на них пришлось 113 млн ₽ - 37% всех потерь за период. Неделя с 29 сентября - пик всего периода: 56 млн ₽ потерь, из них 44 млн - новинки, больше всего iPhone 17 Pro. Главная причина - не квота поставщика, а распределение: на него приходится 60% потерь по новинкам, на дефицит у поставщика - 28%. 62% потерь - дни, когда товар закончился к вечеру: на старте спрос в разы выше обычного, и запаса магазина хватает ненадолго, хотя на складе товар есть. На старт новинки стоит поднимать запасы и частоту пополнения магазинов, а не только объём закупа.

4. Сквозная картина по одному товару

Один товар на всех этапах сразу - iPhone 16 Pro 256GB Black Titanium. Сверху - сколько закупщик заказал и сколько подтвердил поставщик, в середине - остаток каждого склада, внизу - сколько магазинов этого склада были в дефиците. Видно, как недопоставка и неравномерный закуп доходят до полок: пока один склад пуст, у его магазинов растёт дефицит.

iPhone 16 Pro 256GB Black Titanium: закуп, склады и магазиныТовар выбран автоматически - на нём встречается больше всего разных причин дефицита.

5. Хватает ли запасов

Запас в днях - остаток, делённый на средние продажи в день; для склада - на продажи всех его магазинов. В среднем магазин держит 4,4 дня продаж товара, склад - 5,8 дня продаж своего региона. Пары «товар - магазин» и «товар - склад» сгруппированы по среднему запасу, и для каждой группы посчитано, как часто товар был в дефиците.

Доля дней дефицита в зависимости от запасаМагазин - доля дней, когда товара не было весь день или он закончился; склад - доля дней, когда склад пуст. Под столбцом - доля пар в группе.

Склад с запасом до 5 дней продаж региона пуст 25% дней, с запасом 5-7 дней - 5%. Узкое место - склады с малым запасом: так держится 30% пар «товар - склад», и именно они чаще всего оставляют магазины без пополнения.

У магазинов с запасом до 3 дней продаж товар в дефиците 12% дней, с запасом больше 10 дней - 6%. Поднимать запасы магазинов сверх 3-5 дней почти бесполезно: полка пустеет прежде всего тогда, когда пуст склад.

При этом 80% потерь в дни, когда товар закончился за день, пришлись на время, когда товар на складе был: такие магазины можно было пополнить больше или раньше.

6. Прогноз закупа после дефицита

Закупщик заказывает по средним отгрузкам склада за три недели. Пока склад пуст, отгрузок нет, прогноз падает - и следующий заказ снова оказывается маленьким: дефицит продлевает сам себя. Такая ошибка исправляется один раз - изменением правила прогноза.

Ошибки закупа из-за правила прогноза47%от 75 млн ₽ потерь с итогом «ошибка закупа» - без специально заложенных сбоев закупщика

7. Проверка

В симуляцию заранее заложены проблемы на каждом этапе: перебои у поставщика, недозаказы и перезаказы, неравномерный закуп дефицитного товара, пропуски пополнения магазинов. Разбор о них не знает и находит их только по учётным данным.

Верно назван этап цепочки84%потерь, за которыми стоит заложенная проблема
Оценка упущенных продаж308 млн ₽истинные по симуляции - 258 млн ₽

8. Выводы и рекомендации

Дефицит обошёлся сети примерно в 308 млн ₽ за три месяца. Из них 48% - распределение между складом и магазинами, 29% - закуп, 23% - нехватка у поставщика. Значит, большую часть потерь сеть может сократить сама, без изменений у поставщика.

  1. Пополнять магазины, пока на складе есть товар. Распределение - самая дорогая причина: 48% потерь. 80% потерь в дни, когда товар закончился к вечеру, пришлись на время, когда он лежал на складе. Нужен ежедневный отчёт «на складе есть - в магазине пусто или почти пусто» и более частое пополнение быстро продающихся позиций. Запас поднимать не везде, а там, где его меньше 3 дней продаж: в этой группе дефицит 12% дней против 8% при 3-5 днях.
  2. Держать на складах запас хотя бы на 5-7 дней продаж региона. Склад с запасом до 5 дней пуст 25% дней, с запасом 5-7 дней - 5%. Сейчас так мало держится 30% пар «товар - склад»: это точечное изменение закупа по этим позициям, а не рост всех запасов.
  3. Изменить правило прогноза закупа. Прогноз по отгрузкам склада после дефицита занижает следующий заказ - так объясняется 47% потерь с итогом «ошибка закупа». Прогноз стоит строить по продажам магазинов региона в дни, когда товар был, - тогда пустой склад не будет уменьшать заказ.
  4. Готовить старт новинок отдельно. Новинки дали 37% всех потерь за несколько недель продаж. На первые две недели после старта - повышенный запас в магазинах и пополнение по фактическому ажиотажному спросу, а не по обычному плану.
  5. Делить дефицитный товар между складами по спросу. Когда поставщик даёт меньше заказа, перекос закупа стоил 15 млн ₽: один регион получал с запасом, другой оставался пустым. При недопоставке подтверждённый объём стоит распределять пропорционально продажам регионов.
  6. Сделать разбор регулярным. Расчёт работает на данных, которые уже есть в учётной системе. Еженедельная тепловая карта дефицита и разбор причин показывают, кому ставить задачу - закупке, складу или переговорам с поставщиком, - и позволяют проверить, дали ли изменения эффект.

Ноутбук на GitHub