Gloria Food Integration Dumper Version (manually load order)

I know a lot of you guys having hard time following official Gloria integration, I do too. What if I tell you, you don’t need any of those. You can do it with normal Javascript, Actions and Rules. This will give your more control of your flow.

The bad news is this will not be complete tutorial that you will copy and paste and hope it work. I will tell you just the main ingredients you need in order to make it works. You still need to connect the dots to complete the flow.


Before You Start!

  1. The most important thing! You must find a way to stop all of your automations that would interrupt the process. For example, When order add to ticket event or entity changed or selected and a lot more… This is only you would you.
  2. You need to know basic Javascript and JSON object.
  3. Install cURL for Windows

Short Outline for now…

  1. Using Start Process Action to run cURL to download your data.
  2. Using Script to read data. Basically, using ReadFromFile() and JSON.parse().
  3. Manipulate your data, you may need to learn about array.push. You will need to filter out items array and keep only item type “option”. The rest remove from item array and keep whatever you need for ex, discount and delivery fee.
  4. Using {CALL:X} to insert data into Change Ticket Entity, Loop Value & Add Order Action.

Rules
Automation COmmand Executed Rule




Loop Value Rule

1 Like

I’m not programmer. This script very raw and may contains serious bugs. Use at your own risks.

function checkData() {
	var dataFile = "C:\\Users\\thaibistro\\Documents\\SambaPOS5\\Integrations\\gloria-data.txt";
	var curFile = "C:\\Users\\thaibistro\\Documents\\SambaPOS5\\Integrations\\gloria-current.txt";
	var data = file.ReadFromFile(dataFile);
	var newData = {};
	var curData = {};
	for (var i = 0; i < 30; i++) {	
		if (data) {
			data = JSON.parse(data);
			var orders = data.orders;
			if (data.count > 1) {
				newData.count = data.count -1;
				curData.count = 1;
				curData.orders = orders.splice(0,1);
				newData.orders = orders;
				file.WriteToFile(curFile,JSON.stringify(curData));
				file.WriteToFile(dataFile,JSON.stringify(newData));
				preProcessData();
				return getOrderData("recap");
			} else if ( data.count == 1 ) {
				file.WriteToFile(curFile,file.ReadFromFile(dataFile));	
				newData.count = 0;
				file.WriteToFile(dataFile,JSON.stringify(newData));
				preProcessData();
				return getOrderData("recap");
			} else {
				return "Nothing To Do!";
			}
		} else {
			sleep(500);	
		}
		data = file.ReadFromFile(dataFile);
	}	
	return "Something went wrong, No response from website!";
}

function preProcessData() {
	var curFile = "C:\\Users\\Sam\\Documents\\SambaPOS5\\Integrations\\gloria-current.txt";	
	var data = file.ReadFromFile(curFile);
	data = JSON.parse(data);
	data = data.orders[0];
	var filteredItems=[];
	var deliveryFee;
	var tip;
	var discount;
    // Filter out unwanted items
	for (var i = 0; i < data.items.length; i++) {
		if (data.items[i].type == "item") {
			filteredItems.push(data.items[i]);
		} else if (data.items[i].type == "delivery_fee") {
			deliveryFee = data.items[i].price;
		} else if (data.items[i].type == "promo_cart") {
			discount = data.items[i].item_discount;
		} else {
		}
	}
	data.items = filteredItems;
	data.delivery_fee = deliveryFee;
	data.discount = discount;
	file.WriteToFile(curFile,JSON.stringify(data));
	return;	
}

function getOrderData(type,index) {
	var curFile = "C:\\Users\\Sam\\Documents\\SambaPOS5\\Integrations\\gloria-current.txt";	
	var data = file.ReadFromFile(curFile);
	data = JSON.parse(data);
	var items = data.items;
	switch (type) {
		case 'recap':
			var x;
			x  = "Order No: " + data.id + "<br/>";
			x += "Name: " + data.client_first_name + " " + data.client_last_name + "<br/>";
			x += "Type: " + data.type + "<br/>";
			x += "Payment: " + data.payment;
			return x;
		case 'type':
			return ( data.type.toLowerCase() == "delivery" ? "Delivery" : "Take Out" );
		case 'phone':
			return data.client_phone.replace(/\W/g,"");
		case 'client_name':
			return data.client_first_name + " " + data.client_last_name;
		case 'client_address':
                    return data.client_address;
		case 'delivery_fee':
			return data.delivery_fee;
		case 'delivery_note':
			return data.instructions.replace(/\n+|(\r\n)+/g," ");
		case 'discount':
			return data.discount;
		case 'order_id':
			return data.id;
		case 'order_type':
			return data.type;
		case 'payment':
			return data.payment.toUpperCase();
		case 'qty':
			return items[index].quantity;
		case 'name':
			return matchMenuName(items[index].type_id);
		case 'price':
			return items[index].price;
		case 'portion':
			for (var i = 0; i < items[index].options.length; i++) {
				if (items[index].options[i].group_name.indexOf("Extra Protiens") < 0) {
					return items[index].options[i].name.replace("Vegetable","Veggie").replace("& ","");
				}
			}	
			return '';
		case 'tags':
			var tags = [];
			for (var i = 0; i < items[index].options.length; i++) {
				if (items[index].options[i].group_name.indexOf("Soup Choices") > -1) {
					var name = items[index].options[i].name;
					var price = items[index].options[i].price;
					var qty = items[index].options[i].quantity;
					var oi = ( items[index].options[i].group_name.indexOf("Small") > -1 ? 30 : 31 );
					tags.push({
						"OI": oi,
					 	"Q" : qty,
					 	"TN" : items[index].options[i].group_name,
					 	"TV" : name
					});
				}
				if (items[index].options[i].group_name.indexOf("Extra Protiens") > -1) {
					 var name = items[index].options[i].name;
					 var price = items[index].options[i].price;
					 var qty = items[index].options[i].quantity;
					 tags.push({
						"OI": 28,
					 	"Q" : qty,
					 	"TN" : "Default",
					 	"TV" : name,
					 	"PR" : price
					 });
				}
			}
			if (items[index].instructions.length > 0) {
				tags.push({
					"OI":28,
			 		"Q" : 1,
			 		"TN" : "Default",
			 		"TV" : items[index].instructions.replace(/\n+|(\r\n)+/g," ")
				});
			}	
			if (tags.length < 1) return '';
			return JSON.stringify(tags);
		case 'loopValue':
			if (items.length) {
				var c = "0";
				for ( var i = 1; i < items.length; i++) {
					c += ","+ i;
				}
				return c;
			} else {
				return "";
			}
		case '':
			return items.length;
	}
}

function matchMenuName(id) {
    // I use Gloria Food Item ID not Name
	qry  = 'SELECT [Name] FROM [MenuItems] WHERE [CustomTags] LIKE \'' + '%GLF ID%' + id + '%' +'\'';
	menuName = sql.Query(qry).First;
	if (!menuName) return "Misc";
	return menuName;
}

function isNewCustomer() {
	var phone = getOrderData('phone');
	return (api.Entity(phone).Exists() ? '0' : '1');
}

function sleep(milliseconds) {
  var start = new Date().getTime();
  for (var i = 0; i < 1e7; i++) {
    if ((new Date().getTime() - start) > milliseconds){
      break;
    }
  }
}
1 Like

wait for some more info, as I tried 30 times with Gloria some reason its not working form me. and also I don’t need delivery setup ,as we don’t don’t deliver . this simple setup would be good like unconfirmed . than new ticket status it should done in one step hope bu need script this is what I don’t know how to? also delivery setup is another entity screen we already have tables and customers tickets ijust wanted to use within instead creating new screen.

So this means it is requiring someone to be at the terminal to complete the ticket… it does not actually create a ticket? What if two orders get sent same time? I really can’t see how this would be practical. I can see lots of potential issues happening when orders are coming in.

Well, even automate script still need someone to confirm order. I don’t think it is much different.

For multiple orders, you can write script to handle that right. I using it for a week. I still haven’t had multiple orders come in few seconds apart. So, i don’t know if how my script handle multiple orders correctly. I don’t think I (and most small restaurant) going to have a lot of multiple orders in seconds. Unless they too busy to process order but It only take less then 10 sec. to finish order.

No it does not need someone to confirm order. That is just for the entity screen flow. It is actually creating tickets. I modified my entity screen because we do not deliver. My screen just shows when a new order comes in. It auto prints ticket in kitchen and pops up on my screen when customer arrives to pay we just click on it and pay ticket. The tickets are actually already created in the system and submitted I am just using states for an entity flow.

My kitchen staff if we get busy can just simply tap accept in gloria app for each order… sambapos will print all the tickets there is 0 interaction required by SambaPOS for those tickets until customer comes to pay.

2 Likes

If official script works for you is great, but it doesn’t work for me and you can see a lot of ppl having problem because by nature of SambaPOS, everyone has their own way. It is still better then not be able to use it at all.

I don’t think anyone here is successful using official script. That is not the problem with script but most users lack of knowledge of higher level of script so, they can’t edit anything. That is the real problem.

1 Like

Sorry I am not meaning to say your method is bad or wrong. I just wanted to clarify the difference in how it works.

1 Like

Add script and screenshot

1 Like