M cenaly.ru
🍽️ Зал, кухня и учёт

🔮 Прогноз спроса

Медиана по дню недели, план заготовок, черновик закупки и риск «закончится к 19:00»

Документация

Прогноз спроса

Повар каждое утро отвечает на один и тот же вопрос: сколько чего заготовить. Закупщик — на соседний: сколько чего заказать. Обычно оба отвечают по памяти.

Откройте Админ-панель → Склад → вкладка «Прогноз» (admin.cenaly.ru/inventory). Вкладка берёт историю продаж и превращает её в три конкретных артефакта. Порядок на экране — по срочности: сверху то, что рискует закончиться до конца дня, ниже — план заготовок, ещё ниже — черновик заказа поставщику. Если рисковых позиций нет, верхнего блока не будет вовсе. В самом низу, свёрнутой справкой, лежит таблица «Прогноз по блюдам» — на неё можно не смотреть, пока не захотелось проверить цифру.

Доступно на брендах AWS (cenaly.com, cenaly.ru и другие), на cenaly.ru — нет. Аналитическая база платформы, которая считает историю продаж для прогноза, в российском контуре не поднята. Сама вкладка «Прогноз» там открывается, но всегда показывает «Пока мало истории заказов, чтобы прогнозировать спрос» — независимо от того, сколько продаж на самом деле накопилось.


Как считается прогноз#

Ровно две статистики, обе объяснимые повару вслух:

  1. Сколько этого блюда обычно продаётся в этот день недели. Окно истории — 8 недель (56 дней). Точечная оценка — медиана, а не среднее: восемь вторников, один из которых был днём рождения на 40 человек, средним говорят «готовь на 40» каждую неделю, а медиана этот вторник игнорирует. В справочной таблице «Прогноз по блюдам» рядом с числом показан честный разброс наблюдений (минимум–максимум), сколько наблюдений в выборке и пик — часть суток с наибольшей долей продаж. В шапке вкладки написано основание расчёта: «медиана того же дня недели за 56 дней · N рабочих дней истории».
  2. Как этот спрос распределён внутри дня — доли по частям суток: утро (6–11), обед (11–16), вечер (16–23), ночь (23–6). Границы одинаковы для всех заведений, а сам профиль считается по всем дням истории сразу, не отдельно по вторникам.

Что считается наблюдением, тоже решено осознанно: отменённые заказы в историю не идут; сегодняшний незакрытый день в выборку не попадает; дни до первой продажи блюда не считаются нулями (новинка не получает «ноль продаж» за те недели, когда её ещё не было в меню); «день без продаж» отличается от «дня, когда заведение было закрыто». Сутки считаются в часовом поясе локации. В расчёт берутся топ-500 позиций локации по обороту — длинный хвост меню отсекается.

Никакого машинного обучения — и это решение, а не недоделка. У заведения с одной-десятью точками история измеряется десятками недель, а не годами, и её насквозь пробивают выбросы: дождь, концерт по соседству, один щедрый стол. Модели на таких данных подгоняются под шум и выдают уверенные числа, которым нельзя верить.

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

Переключатель вверху выбирает, на какой день строить прогноз — сегодня или завтра.


План заготовок#

Прогноз по блюдам разворачивается по тех-картам в потребность в товарах и полуфабрикатах. Разворот идёт по текущим тех-картам, на момент открытия вкладки — если шеф поменял рецептуру утром, план это учтёт (правку, сделанную в соседнем окне, подхватит обновление страницы).

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

Таблица плана:

Колонка Что означает
Название товара полуфабрикат, который нужно выпустить
Остаток сколько уже есть
Нужно валовая потребность по прогнозу за день
Выпустить нехватка — сколько реально варить/резать
К час, к которому остатка перестаёт хватать

Срок — это не «начало смены». Если соуса хватает на утро, но не на обед, повару надо успеть к 11:00, а не к 6:00. Час округляется до ближайшей границы части суток (6:00, 11:00, 16:00, 23:00), а у вложенных полуфабрикатов срока нет вовсе — там стоит прочерк: их варят «до» того, что из них делают. Строки отсортированы по сроку: раньше дедлайн — выше в списке. Если заготавливать нечего, вкладка так и пишет: остатков хватает на прогноз.

Остаток полуфабриката тратится один раз: если один и тот же бульон входит и в соус, и в суп, наивный расчёт применил бы остаток дважды и закупка недобрала бы сырья.

Кнопка «В доску смены» превращает план в чек-лист задач — см. Доска задач смены. Создаётся одна общая задача «План заготовок — <дата>», а каждая заготовка становится её подзадачей с количеством и часом прямо в заголовке («Соус демиглас — 16 шт к 11:00»); закрыть общую задачу можно только когда закрыты все подзадачи. Повторное нажатие не плодит дубли: если план на эту дату уже стоит на доске, кнопка так и скажет.

Блюда без тех-карты в план не идут и перечисляются отдельным предупреждением (до 20 названий): по ним прогноз ничего сказать не может, и это лучше сказать вслух, чем сделать вид, что заказ полный.


Черновик заказа поставщику#

Ниже плана — черновик закупки на выбранный горизонт покрытия (поле «Покрытие, дней»: обычно срок поставки плюс запас; по умолчанию 3 дня, допустимо от 1 до 30).

Для каждого товара считаются две величины, и берётся бо́льшая:

  • потребность по прогнозу за горизонт минус текущий остаток;
  • добор до целевого остатка (а если он у товара не задан — до точки заказа) — обычная складская логика.

Почему бо́льшая, а не одна вместо другой: страховой запас не знает про завтрашнюю пятницу с двойной посадкой; а прогноз не знает про товары, которые вообще не участвуют в тех-картах (упаковка, расходники) — у них складские нормативы единственный ориентир. Строки, попавшие в список по второму правилу, помечены «по точке заказа». Обратите внимание: правило смотрит на целевой остаток, поэтому в черновик попадёт и товар, который ещё выше точки заказа, но ниже целевого — вкладка «Нужно заказать» такой товар пока не показывает.

По прогнозу закупаются только конечные ингредиенты: полуфабрикаты в заказ поставщику по прогнозу не идут (их выпускают по плану заготовок) — они могут попасть в черновик разве что по складскому нормативу.

Количество округляется вверх до кратности упаковки, если она задана у товара. Строки сгруппированы по поставщикам (товары без назначенного поставщика — отдельной группой), и кнопка создаёт свой заказ на каждого поставщика — дальше это обычные закупки из раздела Склад.


«Закончится к 19:00»#

Самый верхний блок вкладки — риск исчерпания до конца дня: то, что горит прямо сейчас. Он сравнивает текущий остаток с ожидаемым расходом за оставшиеся часы, посчитанным по профилю частей суток, и называет час, к которому остаток обнулится. Если час определить не удаётся, строка честно говорит «не хватит до конца дня», без выдуманного времени.

Блок считается только для сегодня: при переключении на «завтра» он исчезает — риска «закончится к 19:00» у завтрашнего дня не бывает.

Поправка на сегодняшний темп: если к обеду уже израсходовали больше обычного, ожидание на остаток дня пропорционально поднимается, и в строке появляется пометка вроде «темп дня ×1.4». Темп считается по фактическим продажам (списания, порча и питание персонала в него не идут) и измеряется для первых десятка с небольшим самых рискованных строк — остальные считаются по обычному профилю. Коэффициент зажат в диапазоне ×0.5…×2 — поправка на «сегодня людно» нужна, а предсказание по одному чеку нет. Если темп измерить не из чего вообще, вкладка честно скажет, что взят обычный профиль дня недели.


Что нужно, чтобы прогноз появился#

Нужно Зачем Без этого
Бренд на контуре AWS (cenaly.com, cenaly.ru…) историю продаж считает серверная аналитическая база, а она поднята только там на cenaly.ru вкладка всегда пишет «Пока мало истории заказов» — сообщение про историю, но причина другая: считать её там нечем
История продаж посчитать медиану по дню недели «Пока мало истории заказов, чтобы прогнозировать спрос»
≥ 3 одинаковых дня недели в истории считать выборкой блюдо в таблице помечено «мало» и в планы не идёт
Тех-карты блюд развернуть прогноз в товары блюдо попадёт в предупреждение «без тех-карты»
Актуальные остатки посчитать нехватку и риск вкладка не покажет ничего, пока остатки не загрузятся

Агрегат истории пересчитывается на сервере примерно раз в полчаса (и только для аккаунтов, которые сейчас работают); разворот тех-карт и вычет остатков считаются в момент открытия вкладки, по текущим данным.


Связанные разделы#


Частые вопросы#

Почему у половины блюд стоит пометка «мало»?#

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

Почему используется медиана, а не среднее?#

Медиана устойчива к выбросам. Один банкет на 40 человек сдвигает среднее так, что заведение неделями готовит лишнее. Среднее в интерфейсе не показывается вовсе — только медиана, разброс и число наблюдений.

Прогноз учитывает погоду, праздники, футбол?#

Нет. Он знает только день недели и время суток. Праздничную неделю и матч по соседству по-прежнему держит в голове управляющий — и это честнее, чем модель, делающая вид, что учла их.

Можно ли строить прогноз на неделю вперёд?#

Вкладка показывает сегодня и завтра. Для закупки горизонт задаётся отдельно — полем «Покрытие, дней»: прогноз одного дня умножается на него.

Черновик закупки сразу отправляет заказ поставщику?#

Нет. Это именно черновик: лишние строки вы снимаете галочкой и только затем нажимаете создание — получаются обычные черновики закупок раздела «Склад», по одному на поставщика. Количества правятся уже в созданном заказе, там же, где и обычно.