технологические карты
August 28, 2021

Расход товаров и заготовок в Айко с учетом вложенных технологических карт

Задача: рассчитать в Айко расход товара (скажем, "Лосось филе") за день. При условии, что в ресторане заданы вложенные технологические карты и в меню есть составные блюда.

Здесь и далее используются реальные данные реального Клиента, идентификаторы и названия товаров/заготовок/блюд частично "урезаны" для сохранения конфиденциальности.

Дано

В меню ресторана есть три блюда:

  1. Ролл "Маки с лососем" #35c811e50188.
  2. Ролл "Филадельфия с лососем" #35c811e501a7.
  3. Cет "Сет для двоих" #2d2536539600, в составе которого один ролл "Маки с лососем" и один ролл "Филадельфия с лососем".

В Айко (iiko) заданы технологические карты:

  1. Для приготовления 1 кг заготовки "Лосось филе очищенное ПФ" #66e1ee4f2fcc нужно взять 1.299 кг товара "Лосось филе" #35c811e501c6.
  2. Для приготовления 1 блюда "Маки с лососем" #35c811e50188 нужно взять 0.092 кг риса, 1 лист нори и 0.05 кг заготовки "Лосось филе очищенное ПФ" #66e1ee4f2fcc.
  3. Для приготовления 1 блюда "Филадельфия с лососем" #35c811e501a7 нужно взять 0.145 кг риса, 1 лист нори, 0.06 кг крем-сыра, 0.045 кг огурца и 0.1 кг заготовки "Лосось филе очищенное ПФ" #66e1ee4f2fcc.
  4. Для приготовления 1 сета "Сет для двоих" #2d2536539600 нужно взять 1 блюдо "Маки с лососем" #35c811e50188 и одно блюдо "Филадельфия с лососем" #35c811e501a7.

Найти

Менеджер знает, сколько отдельно роллов "Маки с лососем" и "Филадельфия с лососем" было продано за день, сколько было продано сетов "Сет для двоих" за день.

И ему необходимо узнать, сколько же было потрачено лосося за день? Другими словами, какой расход товара "Лосось филе" #35c811e501c6 за день с учетом вложенности технологических карт?

Решение вручную

Схематично дерево приготовления блюд с учетом вложенных технологических карт можно представить в виде:

Состав блюда "Маки с лососем" #35c811e50188:
1. 0.092 кг риса.
2. Один лист нори.
3. 0.05 кг заготовки "Лосось филе очищенное ПФ" #66e1ee4f2fcc. Состав:
    1. 1.299 кг товара "Лосось филе" #35c811e501c6

Состав блюда "Филадельфия с лососем" #35c811e501a7:
1. 0.145 кг риса.
2. Один лист нори.
3. 0.06 кг крем-сыра.
4. 0.045 кг огурца.
5. 0.1 кг заготовки "Лосось филе очищенное ПФ" #66e1ee4f2fcc. Состав:
    1. 1.299 кг товара "Лосось филе" #35c811e501c6    
        
Состав блюда "Сет для двоих" #2d2536539600:
1. Одно блюдо "Маки с лососем ПФ" #35c811e50188. Состав:
    1. 0.092 кг риса.
    2. Один лист нори.
    3. 0.05 кг заготовки "Лосось филе очищенное ПФ" #66e1ee4f2fcc. Состав:
        1. 1.299 кг товара "Лосось филе" #35c811e501c6
2. Одно блюдо "Филадельфия с лососем" #35c811e501a7. Состав:
    1. 0.145 кг риса.
    2. Один лист нори.
    3. 0.06 кг крем-сыра.
    4. 0.045 кг огурца.
    5. 0.1 заготовки "Лосось филе очищенное ПФ" #66e1ee4f2fcc. Состав:
        1. 1.299 кг товара "Лосось филе" #35c811e501c6

Если вручную посчитать, то в одном блюде "Маки с лососем" содержится 0.05 кг заготовки "Лосось филе очищенное ПФ" или 0.05 * 1.299 = 0.06495 кг товара "Лосось филе".

По аналогии: в одном блюде "Филадельфия с лососем" cодержится 0.1 * 1.299 = 0.1299 кг товара "Лосось филе".

В блюде "Сет для двоих" содержится 0.06495 + 0.1299 = 0.19485 кг товара "Лосось филе".

Чтобы дать ответ менеджеру, необходимо построить отчет о продажах за день и сложить произведения:

1. Количество проданных блюд "Маки с лососем" * 0.06495.

2. Количество проданных блюд "Филадельфия с лососем" * 0.1299.

3. Количество проданных блюд "Сет для двоих" * 0.19485.

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

Автоматизация решения

Для решения поставленной задачи внешний разработчик может воспользоваться методами "серверного апи Айко" — iikoServer API. Как подключить внешние интеграции к серверу Айко (iiko) по API

Знакомимся с официальной документацией и экспериментируем с доступными методами API.

1 вариант. Расход продуктов по продажам

А если запросить расход товара "Лосось филе" #35c811e501c6 по продажам за день, что получится?

Расход продуктов по продажам -> /resto/api/reports/productExpense

Вызываем соответствующий метод iikoServer API: /resto/api/reports/productExpense?dateFrom=21.08.2021&dateTo=21.08.2021&hourFrom=-1&hourTo=-1&department=...8a03891ceb68

Указать конкретный идентификатор элемента номенклатуры нельзя, Айко возвращает расход для всех продуктов:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<dayDishValues>
    <dayDishValue>
        <date>21.08.2021</date>
        <productName>Кунжут белый</productName>
        <productId>...35c811e501c2</productId>
        <value>0.388</value>
    </dayDishValue>
    <dayDishValue>
        <date>21.08.2021</date>
        <productName>Лосось филе</productName>
        <productId>...35c811e501c6</productId>
        <value>16.524</value>
    </dayDishValue>
    ...
</dayDishValues>dayDishValues>

Отлично! Видно, что указанная точка доставки реализовала 16.524 кг товара "Лосось филе" #35c811e501c6 за день 21 августа 2021 года.

Что плохо? В списке нет заготовок, только товары (продукты). Разбить расход по часам сразу нельзя, нужно для каждого часа, для каждой точки доставки делать отдельный запрос. У Клиента один запрос в арендованное облако iikoCloud занимает около 30 секунд, не подходит такое решение. Идём дальше.

2 вариант. Вхождение товара в блюдо

Попробуем узнать вхождение товара "Лосось филе" #35c811e501c6 в блюда "Маки с лососем", "Филадельфия с лососем" и "Сет для двоих". Вдруг Айко сразу выдаст нам нужный ответ?

Отчет о вхождении товара в блюдо -> /resto/api/reports/ingredientEntry

Вызываем соответствующий метод iikoServer API: /resto/api/reports/ingredientEntry?date=21.08.2021&product=...35c811e501c6&includeSubtree=false&department=...8a03891ceb68 и получаем ответ:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ingredientEntryDtoes>
    <item>
        <amountInMainUnit>1.299</amountInMainUnit>
        <unit>кг</unit>
        <treeLevel>1</treeLevel>
        <name>Лосось филе очищенное ПФ</name>
        <sourceProduct>
            <id>66e1ee4f2fcc</id>
            <name>Лосось филе очищенное ПФ</name>
            <type>PREPARED</type>
        </sourceProduct>
    </item>
</ingredientEntryDtoes>

Айко отвечает нам: товар "Лосось филе" входит в состав другого элемента номенклатуры — заготовки (type = PREPARED) "Лосось филе очищенное ПФ". Расчета до блюд нет. Значит, нет прямого ответа на наш вопрос? Айко этим методом выдает вхождения только "первого уровня" в дереве технологических карт.

Стоп. У метода есть аргумент includeSubtree (включать ли в отчет строки поддеревьев, по умолчанию false), пробуем задать = true:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<ingredientEntryDtoes>
    <item>
        <amountInMeasureUnit>1.299</amountInMeasureUnit>
        <treeLevel>1</treeLevel>
        <name>Лосось филе очищенное ПФ</name>
        <sourceProduct>
            <id>66e1ee4f2fcc</id>
            <name>Лосось филе очищенное ПФ</name>
            <type>PREPARED</type>
        </sourceProduct>
    </item>
    <item>
        <amountInMeasureUnit>0.064950000</amountInMeasureUnit>
        <treeLevel>2</treeLevel>
        <name>Маки с лососем</name>
        <sourceProduct>
            <id>35c811e50188</id>
            <name>Маки с лососем</name>
            <type>DISH</type>
        </sourceProduct>
    </item>
    <item>
        <amountInMeasureUnit>0.129900</amountInMeasureUnit>
        <treeLevel>2</treeLevel>
        <name>Филадельфия с лососем</name>
        <sourceProduct>
            <id>35c811e501a7</id>
            <name>Филадельфия с лососем</name>
            <type>DISH</type>
        </sourceProduct>
    </item> 
    <item>
        <amountInMeasureUnit>0.064950000</amountInMeasureUnit>
        <treeLevel>3</treeLevel>
        <name>Сет для двоих</name>
        <parentId>83f61602ac51</parentId>
        <sourceProduct>
            <id>2d2536539600</id>
            <name>Сет для двоих</name>
            <type>DISH</type>
        </sourceProduct>
    </item>
    <item>
        <amountInMeasureUnit>0.129900000</amountInMeasureUnit>
        <treeLevel>3</treeLevel>
        <name>Сет для двоих</name>
        <parentId>83f61602ad42</parentId>
        <sourceProduct>
            <id>2d2536539600</id>
            <name>Сет для двоих</name>
            <type>DISH</type>
        </sourceProduct>
    </item>    
</ingredientEntryDtoes>

То, что нужно. Уровень вложенности возвращается в поле <treeLevel>. Обращаем внимание на два последних элемента <item> — они отличаются атрибутом <parentId> (Павел, спасибо за подсказку!) Это значит, что для блюда "Сет для двоих" есть несколько входящих в него элементов номенклатуры, каждый из которых содержит товар "Лосось филе". И чтобы найти итоговое вхождение товара "Лосось филе" в блюдо "Сет для двоих", нужно учесть все эти отдельные вхождения.

Рабочее решение. Финальный алгоритм решения задачи:

1. Заранее строим справочник вхождений исходного товара/заготовки во все блюда ресторана.

2. Строим отчет о продажах за день.

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

3 вариант. Получение технологических карт

Внешний разработчик может выгрузить через iikoServer API все действующие и удаленные технологические карты.

https://ru.iiko.help/articles/#!api-documentations/recipes

Важное замечание из официальной документации:

Технологические карты (рецепты) в iiko строго привязаны к элементам номенклатуры (блюдам, модификаторам, заготовкам) и датам: на каждый учетный день элементу номенклатуры может быть сопоставлено не более одной технологической карты. Единственная сопоставленная карта должна задавать метод списания (целиком/по ингредиентам) и состав+количество ингредиентов для всех действующих и удаленных подразделений, размеров блюд.
Ингредиентом блюда, модификатора, заготовки может быть заготовка, имеющая свою собственную технологическую карту. Таким образом, техкарты образуют деревья.

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

Но подробнее о технологических картах в другой раз 😉

Отчет Семёна Фудова

У Сёмена Фудова есть такой отчет — "Расход заготовок", в котором есть ответ на вопрос: "Сколько-таки лосося было израсходовано за день?" С разбивкой по отдельным точкам доставки, по часам.

Если заинтересовались в таком отчете для своей службы доставки — пишите на почту hello@fudov.ru, подключим.

Расход заготовок, fudov.ru