Make an order
This is a part of the tutorial on creating a button-based bot that can order pizza.
- Selecting a delivery city
- Creating a dictionary
- Selecting a pizza
- Making an order (you are here)
- 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);
}
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
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.
Next, move on to testing the whole bot script.