Выбор пиццы
На этом шаге создадим сценарий, в котором бот будет предлагать клиенту пиццу на выбор, а затем формировать заказ.
Создание сценария
Создайте файл сценария pizza.sc в папке src.
require: pizza.csv
    name = pizza
    var = pizza
theme: /
    state: ChoosePizza
        a: Какую пиццу будем заказывать сегодня?
        script:
            for (var id = 1; id < Object.keys(pizza).length + 1; id++) {
                var regions = pizza[id].value.region;
                if (_.contains(regions, $client.city)) {
                    var button_name = pizza[id].value.title;
                    $reactions.buttons({text: button_name, transition: 'GetName'})
                }
            }
        state: GetName
            script:
                $session.pizza_name = $request.query;
            go!: /ChooseVariant
        state: ClickButtons
            q: *
            a: Нажмите, пожалуйста, кнопку.
            go!: ..
    state: ChooseVariant
        a: Выберите, пожалуйста, вариант:
        script:
            for (var id = 1; id < Object.keys(pizza).length + 1; id++) {
                if ($session.pizza_name == pizza[id].value.title) {
                    var variations = pizza[id].value.variations;
                    for(var i = 0; i < variations.length; i++){
                        var button_name = variations[i].name + " за " + variations[i].price + " руб."
                        $reactions.inlineButtons({text: button_name, callback_data: variations[i].id })
                    }
                }
            }
        a: Для возврата в меню выбора пиццы, нажмите "Меню"
        buttons:
            "Меню" -> /ChoosePizza
        state: ClickButtons
                q: *
                a: Нажмите, пожалуйста, кнопку.
                go!: ..
    state: GetVariant
        event: telegramCallbackQuery
        script:
            $session.pizza_id = parseInt($request.query);
        go!: /ChooseQuantity
    state: ChooseQuantity
        a: Выберите, пожалуйста, количество:
        buttons:
            "1" -> ./GetQuantity
            "2" -> ./GetQuantity
            "3" -> ./GetQuantity
        state: ClickButtons
                q: *
                a: Нажмите, пожалуйста, кнопку.
                go!: ..
        state: GetQuantity
            script:
                $session.quantity = parseInt($request.query);
                $session.cart.push({name: $session.pizza_name, id: $session.pizza_id, quantity: $session.quantity});
            a: Хотите ли выбрать что-нибудь еще, или перейдем к оформлению заказа?
            buttons:
                "Меню" -> /ChoosePizza
            buttons:
                "Оформить заказ" -> /Cart
            state: ClickButtons
                q: *
                a: Нажмите, пожалуйста, кнопку.
                go!: ..
Подключение модулей
В начале сценария под тегом require подключаем справочник pizza.csv. Здесь var = pizza указывает на то, что далее обращаться к справочнику можно по ключевому слову pizza.
require: pizza.csv
    name = pizza
    var = pizza
Теперь подключим сценарий pizza.sc к основному сценарию main.sc:
require: pizza.sc
Стейты
Сценарий бота состоит из следующих стейтов:
ChoosePizza— выбор пиццы из справочника.GetName— сохранение выбранного клиентом варианта.ChooseVariant— выбор вариантов приготовления пиццы.GetVariant— сохранение параметров для выбранной пиццы.ChooseQuantity— выбор количества пиццы для заказа.GetQuantity— сохранение введенного количества пиццы.
Структура сценария
ChoosePizza
На этом этапе клиент уже выбрал город, в котором он хочет заказать пиццу. Поэтому выведем из каталога список из пицц, доступных в этом городе.
state: ChoosePizza
    a: Какую пиццу будем заказывать сегодня?
    script:
        for (var id = 1; id < Object.keys(pizza).length + 1; id++) {
            var regions = pizza[id].value.region;
            if (_.contains(regions, $client.city)) {
                var button_name = pizza[id].value.title;
                $reactions.buttons({text: button_name, transition: 'GetName'})
            }
        }
В скрипте стейта ChoosePizza обращаемся к справочнику pizza.csv и выбираем названия пицц, которые можно заказать в выбранном городе. Затем с помощью функции $reactions.buttons используем выбранные параметры в качестве названия кнопок и добавляем переход в стейт GetName.
GetName
Теперь сохраним выбор клиента. В скрипте стейта GetName сохраняем название выбранной пиццы в переменную $session.pizza_name. Мы сможем использовать её для получения доступа к информации о данной пицце и отображения ее названия в корзине. Затем осуществим переход в стейт ChooseVariant.
state: GetName
    script:
        $session.pizza_name = $request.query;
    go!: /ChooseVariant
ChooseVariant
В скрипте стейта ChooseVariant, по аналогии со скриптом для выбора пиццы, создаем кнопки для выбора варианта приготовления. На этот раз воспользуемся функцией $reactions.inlineButtons. В отличие от $reactions.buttons такие кнопки отображаются внутри диалога в виде реплик бота.
state: ChooseVariant
    a: Выберите, пожалуйста, вариант:
    script:
        for (var id = 1; id < Object.keys(pizza).length + 1; id++) {
            if ($session.pizza_name == pizza[id].value.title) {
                var variations = pizza[id].value.variations;
                for(var i = 0; i < variations.length; i++){
                    var button_name = variations[i].name + " за " + variations[i].price + " руб."
                    $reactions.inlineButtons({text: button_name, callback_data: variations[i].id })
                }
            }
        }
    a: Для возврата в меню выбора пиццы, нажмите "Меню"
        buttons:
            "Меню" -> /ChoosePizza
GetVariant
В стейте GetVariant событие telegramCallbackQuery срабатывает по клику на инлайн-кнопку из стейта ChooseVariant. В скрипте сохраняем параметры пиццы в переменную $session.pizza_id. Мы сможем использовать её для получения доступа к информации о данной пицце и отображения ее в корзине. Затем осуществляем переход в стейт ChooseQuantity для выбора количества пицц.
state: GetVariant
    event: telegramCallbackQuery
    script:
        $session.pizza_id = parseInt($request.query);
    go!: /ChooseQuantity
ChooseQuantity
В стейте ChooseQuantity клиент выбирает количество пицц кликом на соответствующую кнопку и переходит в стейт GetQuantity.
state: ChooseQuantity
    a: Выберите, пожалуйста, количество:
    buttons:
        "1" -> ./GetQuantity
        "2" -> ./GetQuantity
        "3" -> ./GetQuantity
GetQuantity
В скрипте стейта GetQuantity сохраняем количество выбранных пицц в переменную $session.quantity, а также добавляем выбранный вариант в корзину с помощью функции $session.cart.push.
Далее добавим две кнопки Меню и Оформить заказ. По ним будем решать, в какой стейт отправить клиента дальше: обратно в меню или к корзине для оформления заказа.
state: GetQuantity
    script:
        $session.quantity = parseInt($request.query);
        $session.cart.push({name: $session.pizza_name, id: $session.pizza_id, quantity: $session.quantity});
    a: Хотите ли выбрать что-нибудь еще, или перейдем к оформлению заказа?
    buttons:
        "Меню" -> /ChoosePizza
    buttons:
        "Оформить заказ" -> /Cart
ClickButtons
Добавим вложенный стейт ClickButtons в стейты ChoosePizza, ChooseVariant и ChooseQuantity. Он будет выполнять такую же функцию, как и в сценарии main.sc.
state: ClickButtons
    q: *
    a: Нажмите, пожалуйста, кнопку.
    go!: ..
Тестирование
Протестируем результат работы сценария в Telegram. Результат запуска:
Далее перейдем к оформлению заказа.