Skip to content

Instantly share code, notes, and snippets.

@emreeren
Created February 27, 2017 23:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save emreeren/0d26aca9b83415fa01fcc3b5d2f172ad to your computer and use it in GitHub Desktop.
Save emreeren/0d26aca9b83415fa01fcc3b5d2f172ad to your computer and use it in GitHub Desktop.
var express = require('express');
var request = require('request');
var querystring = require('querystring');
var messageServer = 'localhost';
var messageServerPort = 9000;
var gloriaFoodKey = 'xxxxxxxxxxxxxxxxxx';
var serverKey = 'xxxxxxxxxxxxxxxxxxx';
var timeout = 30000;
var customerEntityType = 'Customers';
var itemTagName = 'Gloria Name';
var ticketType = 'Delivery Ticket';
var departmentName = 'Restaurant';
var userName = 'Administrator';
var terminalName = 'Server';
var printJobName = 'Print Orders to Kitchen Printer';
var miscProductName = 'Misc';
var deliveryFeeCalculation = 'Delivery Service';
var tipCalculation = 'Tip';
var accessToken = undefined;
var accessTokenExpires = '';
Authorize(loop());
function Authorize(callback) {
accessToken = undefined;
var form = { grant_type: 'client_credentials', client_secret: serverKey, client_id: 'gloria' };
var formData = querystring.stringify(form);
var contentLength = formData.length;
request({
headers: {
'Content-Length': contentLength,
'Content-Type': 'application/x-www-form-urlencoded'
},
uri: 'http://' + messageServer + ':' + messageServerPort + '/Token',
body: formData,
method: 'POST'
}, function (err, res, body) {
if (err) {
console.log('Error while trying to authorize >', err.message);
}
else if (res.statusCode === 400) {
console.log(body);
if (callback) callback();
}
else {
var result = JSON.parse(body);
accessToken = result.access_token;
accessTokenExpires = new Date(result['.expires']);
if (callback) callback();
}
});
}
function gql(query, callback) {
if (!accessToken) {
console.log('Valid access Token is needed to execute GQL calls.')
return;
}
var data = JSON.stringify({ query: query });
request({
headers: {
'Content-Type': 'application/json',
'Accept': 'application/json',
'Authorization': 'Bearer ' + accessToken
},
uri: 'http://' + messageServer + ':' + messageServerPort + '/api/graphql',
body: data,
method: 'POST'
}, function (err, res, body) {
if (res.statusCode === 401) {
console.log('Should Authorize...');
Authorize(() => gql(query, callback));
}
else {
var data = JSON.parse(body).data;
if (callback) callback(data);
}
});
}
function readTickets(callback) {
request({
method: 'POST',
uri: 'https://pos.gloriafood.com/pos/order/pop',
headers: {
'Authorization': gloriaFoodKey,
'Accept': 'application/json',
'Glf-Api-Version': '2'
}
}, function (err, res, body) {
if (err) {
console.log(`problem with request: ${err.message}`);
} else {
callback(JSON.parse(body));
}
});
}
function loop() {
if (!accessToken) {
console.log('There is no valid access token. Skipping...')
Authorize();
}
else if (accessTokenExpires < new Date()) {
console.log('Access Token Expired. Reauthenticating...');
Authorize(() => loop());
return;
}
else {
console.log('Reading Tickets...');
readTickets((tickets) => processTickets(tickets));
}
setTimeout(loop, timeout);
}
function processTickets(tickets) {
if (tickets.count == 0) return;
tickets.orders.forEach((order) => processOrder(order));
}
function processOrder(order) {
var customer = {
firstName: order.client_first_name,
lastName: order.client_last_name,
email: order.client_email,
phone: order.client_phone,
address: order.client_address,
newCustomer: false
}
loadCustomer(customer, customer => {
var services = order.items
.filter(x => x.type === 'tip' || x.type === 'delivery_fee')
.map(x => { return { name: getCalculationName(x.type), amount: x.price }; })
.filter(x => x.name);
loadItems(order.items.map(x => processItem(x)), items => {
createTicket(customer, items, order.fulfill_at, services, ticketId => {
gql('mutation m {postTicketRefreshMessage(id:0){id}}', () => {
console.log(`Ticket ${ticketId} created...`);
});
});
});
});
}
function getCalculationName(name) {
if (name === 'tip') return tipCalculation;
if (name === 'delivery_fee') return deliveryFeeCalculation;
return undefined;
}
function loadItems(items, callback) {
var script = getLoadItemsScript(items);
gql(script, data => {
callback(items.filter(x => x.type === 'item').map(item => {
return {
id: item.id,
name: item.name,
type: item.type,
sambaName: data[`i${item.id}`][0] ? data[`i${item.id}`][0].name : miscProductName,
price: item.price,
quantity: item.quantity,
options: item.options
}
}));
});
}
function isNewCustomer(customer) {
if (customer.states && customer.states.find(x => x.stateName === 'CStatus')) {
return customer.states.find(x => x.stateName === 'CStatus').state === 'Unconfirmed';
}
return false;
}
function createTicket(customer, items, fulfill_at, services, callback) {
var newCustomer = isNewCustomer(customer);
gql(getAddTicketScript(items, customer.name, newCustomer, fulfill_at, services), data => {
if (newCustomer)
callback(data.addTicket.id);
else printTicketToKitchen(data.addTicket.id, () => callback(data.addTicket.id));
});
}
function printTicketToKitchen(ticketId, callback) {
gql(getKitchenPrintScript(ticketId), callback);
}
function loadCustomer(customer, callback) {
gql(getIsEntityExistsScript(customer), (data) => {
if (!data.isEntityExists) {
createCustomer(customer, callback);
} else getCustomer(customer.phone, callback);
});
}
function createCustomer(customer, callback) {
gql(getAddCustomerScript(customer), (data) => {
gql(getNewCustomerStateScript(customer), () => {
getCustomer(data.addEntity.name, callback);
})
});
}
function getCustomer(customerName, callback) {
gql(getCustomerScript(customerName), (data) => {
callback(data.getEntity);
});
}
function getLoadItemsScript(items) {
var part = items.map(item => `i${item.id}: getProducts(itemTag:{name:"${itemTagName}",value:"${item.name}"}){name} `);
return `{${part}}`;
}
function getCustomerScript(name) {
return `{getEntity(type:"${customerEntityType}",name:"${name}"){name,customData{name,value},states{stateName,state}}}`;
}
function getIsEntityExistsScript(customer) {
return `{isEntityExists(type:"${customerEntityType}",name:"${customer.phone}")}`;
}
function getAddCustomerScript(customer) {
return `
mutation m{addEntity(entity:{
entityType:"${customerEntityType}",name:"${customer.phone}",customData:[
{name:"First Name",value:"${customer.firstName}"},
{name:"Last Name",value:"${customer.lastName}"},
{name:"Address",value:"${customer.address}"},
{name:"EMail",value:"${customer.email}"}
]})
{name}
}`;
}
function getNewCustomerStateScript(customer) {
return `mutation m{updateEntityState(entityTypeName:"${customerEntityType}",entityName:"${customer.phone}",state:"Unconfirmed",stateName:"CStatus"){name}}`;
}
function getKitchenPrintScript(ticketId) {
return `mutation m {
executePrintJob(name: "${printJobName}", ticketId: ${ticketId},
orderStateFilters: [{stateName: "Status", state: "New"}],
nextOrderStates:[{stateName:"Status",currentState:"New",state:"Submitted"}])
{name}
}`;
}
function GetOrderTags(order) {
if (order.options) {
var options = order.options.map(x => `{tagName:"Default",tag:"${x.name}",price:${x.price},quantity:${x.quantity}}`);
var result = options.join();
return `tags:[${result}],`
}
return "";
}
function GetOrderPrice(order) {
if (order.price > 0)
return `price:${order.price},`;
return "";
}
function getAddTicketScript(orders, customerName, newCustomer, fulfill_at, services) {
var orderLines = orders.map(order => {
return `{
name:"${order.sambaName ? order.sambaName : order.name}",
menuItemName:"${order.sambaName === miscProductName ? order.name : ''}",
quantity:${order.quantity > 0 ? order.quantity : 1},
${GetOrderPrice(order)}
${GetOrderTags(order)}
states:[
{stateName:"Status",state:"New"}
]
}`;
});
var entityPart = customerName
? `entities:[{entityType:"${customerEntityType}",name:"${customerName}"}],`
: '';
var calculationsPart = services
? `calculations:[${services.map(x=>`{name:"${x.name}",amount:${x.amount}}`).join()}],`
: '';
var result = `
mutation m{addTicket(
ticket:{type:"${ticketType}",
department:"${departmentName}",
user:"${userName}",
terminal:"${terminalName}",
${entityPart}
states:[
{stateName:"Status",state:"Unpaid"},
{stateName:"Source",state:"Gloria"},
{stateName:"Delivery",state:"${newCustomer ? 'Unconfirmed' : 'Waiting'}"}
],
tags:[{tagName:"Delivery Minutes",tag:"${Math.ceil(Math.abs(new Date(fulfill_at) - Date.now()) / 60000)}"}],
${calculationsPart}
orders:[${orderLines.join()}]
}){id}}`;
return result;
}
function processItem(item) {
var result = {
id: item.id,
name: item.name,
type: item.type,
price: item.price,
quantity: item.quantity,
options: item.options.map(x => { return { name: x.name, quantity: x.quantity, price: x.price } })
};
return result;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment