Skip to main content

Make an order

This is a part of the tutorial on creating a button-based bot that can order pizza.

  1. Selecting a delivery city
  2. Creating a dictionary
  3. Selecting a pizza
  4. Making an order (you are here)
  5. Testing the bot script

At the previous step, we’ve created the pizza.sc script where the client chooses the pizza they would like to order and adds it to the cart.

At this step, we will create a script and functions for placing an order.

Functions for working with the cart

Create function.js file in the src folder and paste the following:

function deleteFromCart(name){
var $session = $jsapi.context().session;
for(var i = 0; i < $session.cart.length; i++){
var current_position = $session.cart[i];
if(current_position.name === name){
$session.cart.splice(i, 1);
}
}
log('!!!!!! CART: ' + JSON.stringify($session.cart));
}

function getTotalSum(){
var totalSum = 0;
var $session = $jsapi.context().session;

for(var i = 0; i < $session.cart.length; i++){
var current_position = $session.cart[i];
for(var id = 1; id < Object.keys(pizza).length + 1; id++){
if (current_position.name === pizza[id].value.title){
var variation = _.find(pizza[id].value.variations, function(variation){
return variation.id === current_position.id;
});
totalSum += variation.price * current_position.quantity;
}
}
}
log("!!!!!!!!!!!! totalSum = " + totalSum);
return totalSum;
}

function editText(messageId, text) {
var $response = $jsapi.context().response;
var reply = {
type: "raw",
body: {
text: text,
message_id: messageId,
reply_markup: {
"resize_keyboard": false,
}
},
method: "editMessageText"
};

$response.replies = $response.replies || [];
$response.replies.push(reply);
}

Here:

  • function deleteFromCart(name) — removing an item from the cart;
  • function getTotalSum() — calculating the total cost of the order;
  • function editText(messageId, text) — editing previous messages.

deleteFromCart ()

The deleteFromCart() function removes the selected item from the cart.

function deleteFromCart(name){
var $session = $jsapi.context().session;
/* looking through the elemenets of the cart
until we find the item to delete */
for(var i = 0; i < $session.cart.length; i++){
var current_position = $session.cart[i];
if(current_position.name === name){
$session.cart.splice(i, 1);
}
}
// display the result in the logs
log('!!!!!! CART: ' + JSON.stringify($session.cart));
}

The function takes an item name as an input variable. If the item name matches the input variable name, the selected item is removed from the array using the splice() method.

Then, using the log function, display a message about the changes made. When an item is deleted, the following message appears in the Logs tab:

!!!!!! CART: [{"name":"Pepperoni","id":7,"quantity":1}]

getTotalSum ()

The getTotalSum() function returns the items total sum in the cart.

function getTotalSum(){
// initialize the total sum variable
var totalSum = 0;
var $session = $jsapi.context().session;

// count the total sum
for(var i = 0; i < $session.cart.length; i++){
var current_position = $session.cart[i];
for(var id = 1; id < Object.keys(pizza).length + 1; id++){
if (current_position.name === pizza[id].value.title){
var variation = _.find(pizza[id].value.variations, function(variation){
return variation.id === current_position.id;
});
totalSum += variation.price * current_position.quantity;
}
}
}
// display the result in the logs
log("!!!!!!!!!!!! totalSum = " + totalSum);
return totalSum;
}

editText ()

The editText() function edits bot’s previous messages after deleting the product using editMessageText method. When the item is deleted, the deleted item name changes to Deleted.

function editText(messageId, text) {
var $response = $jsapi.context().response;
var reply = {
type: "raw",
body: {
text: text,
message_id: messageId,
reply_markup: {
"resize_keyboard": false,
}
},
method: "editMessageText"
};

$response.replies = $response.replies || [];
$response.replies.push(reply);
}
caution
Please note, that previous messages editing is only available in Telegram.

Now that we’ve created functions for cart editing, we move on to working with the script.

Creating the script

Create the cart.sc file in the src folder and paste the following:

require: function.js

theme: /

state: Cart
intent!: /cart
a: Your cart
script:
$temp.totalSum = 0;
var n = 0;
for(var i = 0; i < $session.cart.length; i++){
var current_position = $session.cart[i];
for(var id = 1; id < Object.keys(pizza).length + 1; id++){
if (current_position.name == pizza[id].value.title){
var variation = _.find(pizza[id].value.variations, function(variation){
return variation.id === current_position.id;
});

n++;

if (!variation) {
$reactions.answer("Failed on request processing, no option is found for id " + current_position.id);
} else {
$reactions.answer(n + ". " + current_position.name + ", " + variation.name + "\nPrice: " + variation.price + "\nQuantity: " + current_position.quantity);

$reactions.inlineButtons({text: "Remove", callback_data: current_position.name});

$temp.totalSum += variation.price * current_position.quantity;
}
}
}
}
$session.messageId = $request.rawRequest.message.message_id + n + 2;

a: Total sum: {{ $temp.totalSum }} $.
a: If everything is correct, send your phone number and our manager will contact you.
buttons:
{text: "Send phone number", request_contact: true}
"Menu" -> /ChoosePizza

state: Edit
event: telegramCallbackQuery
script:
var name = $request.rawRequest.callback_query.data;
deleteFromCart(name);
var message_id = $request.rawRequest.callback_query.message.message_id;

editText(message_id, 'Removed');
editText($session.messageId, 'Total sum: ' + getTotalSum() + ' $');
if: $session.cart.length == 0
a: Your cart is empty
go!: /ChoosePizza

state: ClickButtons
q: *
a: Please, click the button.
go!: ..

state: GetPhoneNumber
event: telegramSendContact
script:
$client.phone_number = $request.rawRequest.message.contact.phone_number;
a: Thank you! Our manager will contact you by phone number {{ $client.phone_number }}.

Adding modules

At the beginning of the script, under the require tag, include the function.js file.

require: function.js

Then include the cart.sc script to the main.sc script:

require: cart.sc

States

The script consists of a few states:

  • Cart — displaying the content of the cart and the total order amount.
  • Edit — editing the cart content.
  • GetPhoneNumber — sending a phone number for order confirmation.

Script structure

Cart

To check the items in the cart, create the cart state and paste the following:

state: Cart
intent!: /cart
a: Your cart
script:
$temp.totalSum = 0;
var n = 0;
for(var i = 0; i < $session.cart.length; i++){
var current_position = $session.cart[i];
for(var id = 1; id < Object.keys(pizza).length + 1; id++){
if (current_position.name == pizza[id].value.title){
var variation = _.find(pizza[id].value.variations, function(variation){
return variation.id === current_position.id;
});
n++;

if (!variation) {
$reactions.answer("Failed on request processing, no option is found for id " + current_position.id);
} else {
$reactions.answer(n + ". " + current_position.name + ", " + variation.name + "\nPrice: " + variation.price + "\nQuantity: " + current_position.quantity);

$reactions.inlineButtons({text: "Remove", callback_data: current_position.name});

$temp.totalSum += variation.price * current_position.quantity;
}
}
}
}
$session.messageId = $request.rawRequest.message.message_id + n + 2;

a: Total sum: {{ $temp.totalSum }} $.
a: If everything is correct, send your phone number and our manager will contact you.
buttons:
{text: "Send phone number", request_contact: true}
"Menu" -> /ChoosePizza

Intent

The transition to the cart state is triggered by a /cart intent.

Go to the NLU > Intents tab on the control panel. Create the /cart intent and add the following phrases to the Training phrases field:

cart
what's in the cart
show cart
open cart

Creating cart intent

Script

Here the bot displays a list of items in the cart and its total price.

Let’s create a $temp.totalSum variable to which we’ll be adding the price of items.

script:
$temp.totalSum = 0;
var n = 0;
for(var i = 0; i < $session.cart.length; i++){
var current_position = $session.cart[i];
for(var id = 1; id < Object.keys(pizza).length + 1; id++){
if (current_position.name == pizza[id].value.title){
var variation = _.find(pizza[id].value.variations, function(variation){
return variation.id === current_position.id;
});

n++;

if (!variation) {
$reactions.answer("Failed on request processing, no option is found for id " + current_position.id);
} else {
$reactions.answer(n + ". " + current_position.name + ", " + variation.name + "\nPrice: " + variation.price + "\nQuantity: " + current_position.quantity);

$reactions.inlineButtons({text: "Remove", callback_data: current_position.name});
$temp.totalSum += variation.price * current_position.quantity;
}
}
}
}
$session.messageId = $request.rawRequest.message.message_id + n + 2;

Now we have to ask the client for their phone number to complete the order. To do this, add two buttons: Send phone number and Menu. The Send phone number button calls the request_contact telegram API method to send the phone number, and the Menu button switches the dialog to the ChoosePizza state.

a: If everything is correct, send your phone number and our manager will contact you.
buttons:
{text: "Send phone number", request_contact: true}
"Menu" -> /ChoosePizza

Edit

Telegram supports editing previous messages. If the client decides to delete any item from the cart, the bot must report the changes and recalculate the total order sum.

While editing, we replace the name of the removed pizza with the Removed message. If the cart is empty, the bot displays the message Your cart is empty and moves to the ChoosePizza state.

state: Edit
event: telegramCallbackQuery
script:
var name = $request.rawRequest.callback_query.data;
deleteFromCart(name);
var message_id = $request.rawRequest.callback_query.message.message_id;

editText(message_id, 'Removed');
editText($session.messageId, 'Total sum: ' + getTotalSum() + ' $');
if: $session.cart.length == 0
a: Your cart is empty
go!: /ChoosePizza

Add the nested ClickButtons state. It performs the same way as in the main.sc script.

state: ClickButtons
q: *
a: Please, click the button.
go!: ..

GetPhoneNumber

To confirm an order, we ask the client to send their phone number. The telegramSendContact event is triggered when the client sends their number. The received number is stored in the $client.phone_number variable.

state: GetPhoneNumber
event: telegramSendContact
script:
$client.phone_number = $request.rawRequest.message.contact.phone_number;
a: Thank you! Our manager will contact you by phone number {{ $client.phone_number }}.

Testing

Let’s test the result in the Telegram.

Telegram channel Telegram channel Telegram channel

Next, move on to testing the whole bot script.