GQL Modules - GraphQL Modules for Remote Client Browsers


I don’t think there is anything in GraphQL that has that functionality.

Not sure why Free Tagging config should make a difference. Might be a limitation to the GQL Query that it ignores Order Tags that have Free Tagging set. Would have to test that to know for sure. The Query I use is:


There is another Query that is similar that I used to use, but not any longer, and the code is commented out:



Yes i saw that. But what if we have a ticket tag where we would make a selection before actually taking orders. For example a client of mine has setup pax where they record how many people are at a table and they insert a number from selection all prior to ticket creation.
Im sure this hasnt been implemented yet but im wondering if there are any gql codes for it similar to the way its setup for order tags


Yes, you can set Ticket Tags using the updateTerminalTicket() mutation:

mutation m {updateTerminalTicket(terminalId:"asdfasdfasdf",tags:[{tagName:"PAX",tag:"10"}]){id,number,uid,tags{tagName,tag}}}

I can see I have that mutation in gqlqueries.js but it is incomplete because it is a “newish” mutation and I never fleshed it out yet:

gql.updateTerminalTicket = function(terminalId,note,tags,states) {
    return 'mutation m {terminalTicket:updateTerminalTicket(terminalId:"'+terminalId+'")'+gql.terminalTicketDetails()+'}';

It should be something like this instead:

gql.updateTerminalTicket = function(terminalId,note,tags,states) {
    var q = 'mutation m {terminalTicket:updateTerminalTicket(terminalId:"'+terminalId+'"';
    q += note ? ',note:"'+note+'"' : '';
    q += tags ? ',tags:' + tags : '';
    q += states ? ',states:' + states : '';
    q += ')';
    q += gql.terminalTicketDetails();
    q += '}';
    return q;

You need to ensure the parameters that you send to that function for tags and states are Arrays, like:

var someTags = ['{tagName:"PAX",tag:"10"}','{tagName:"TA",tag:"Dine In"}'];
var someStates = ['{stateName:"VIP",state:"Active"}'];

Anyway, you need to add a button somewhere, probably in the same section as the Print buttons, and when clicked have it prompt for a value and then execute that mutation.


I updated the code to use updateTerminalTicket mutation instead of updateTerminalTicket mutation. This works much better for setting Ticket Note. The old method required an existing Ticket (ie. ticket != 0) while the new method does not - it works off the terminalTicket.uid instead.

NOTE: Github NOT updated, yet, because …

I now want to expand this overlay dialog to contain more functionality. Currently it simply shows some minor Ticket Details and accepts setting the Ticket Note …

Looking for suggestions (mockups would be great) regarding how we can fill this out to provide more detail and functionality, because i don’t really need anything here for my purpose, but I’m sure others could use some more “stuff” here.

I am going to start with putting some Print Jobs in here, like Print Bill.


As of now im just brainstorming pretty much the entire code and layout to get ideas on how everything works and is connected because im very new to this world of coding haha.

But im getting a lot of the stuff written… which is a good start.

Honestly i think having ticket tags is really good to have there if defined or even if possible to be able to set free tagging and save them. So having like a dialogue box that could insert data into that ticket tag group.

But we also have to think about what if there is more than one ticket tag group.

Ticket commands. Could you give me an example of what type of ticket command?

The print jobs buttons would be really good to have as i can see a lot of staff using that feature to print bills on request.

Automation commands such as custom change price or misc item would be really good to have imho(in my honest opinion)

Maybe i could request from emre a new mutation that would allow the free tagging for order tags to allow custom order tags dialogue to work under item order tags

Edit: also some ticket tags may require selection before creating ticket. Ive looked at the code above but im curious as to which file and roughly where i woukd either update or insert that code


All I mean by that is something like an Automation Command that invokes a Ticket-level operation. Similar to a Ticket Tag but not that specific. Maybe like a Ticket Discount.

Those are Order-level operations, so they need to go somewhere else.


I had to change the code for Ticket Note, and Ticket Tags and States are part of the same mutation. I will take care of that in the next Git push - that’s why I’m fishing for ideas, because it could change the flow of the code.


Ticket discounts would be good. Based on predefined % or user input.

Also that ticket lister module. Could we make it so that when you select a ticket it comes to middle of screen which is fine but could we go further by adding a button which opens that ticket up. Similar to the way ticket lister on pos screen module works.

Maybe we could even add payment info to ticket note too after viewing a paid ticket?


We could do predefined discounts (Calculations) using Automation Commands. But getting user Input for such things will need to be custom coded.

I don’t understand what you mean here. When you click on a Ticket, it does open up…

Some of my progress so far…

It seems we don’t really need Print Jobs, because we can handle Print Jobs with Automation Commands …

So if I leave Print Jobs out (POS_PrintJobs = [];) then it looks like the following. It was redundant before.

// POS
var menuName        = 'Menu';
var departmentName  = 'Restaurant';
var ticketTypeName  = 'Ticket';
var POS_EntityTypes = ['Tables','Customers'];
var POS_EntityTypesAuto = false; // override static Entity Types above with automatic Ticket Type Entity Types
// Automation Commands that appear at the Ticket-level
var POS_TicketCommands = ['Print Bill','Print Order','WIFI Show Password'];
// Automation Commands that appear at the Order-level
var POS_OrderCommands  = ['Print Order Lines'];
// you can specify Print Jobs here, but in general, Automation Commands will handle firing Print Jobs
var POS_PrintJobs   = []; // ['Print Bill','Print Orders to Kitchen Printer'];

FYI, the AMC named WIFI Show Password actually fires a Print Job to my Pole Display to show the WiFi Password and it works! So does the Print Bill button!

I am going to work on getting the defined AMC Headers and Button Colors. We have a “Special Report” named GQLM Automation Commands for that already, so we have all of that data on hand…

EDIT: scratch that… we have a GQL Query for that (of course!) …

mutation m {
  automationCommands: getAutomationCommandButtonsForTerminalTicket(terminalId: "UuDkN9d6zkSe1GUXv8VPnw", orderUids: "") {


Im not at my pc right now but i think its your ticket explorer module you find on the main menu screen. When you go to that module and highlight a ticket on the left hand side it shows the order and ticket info in middle of the screen but you cant open it in pos mode where you could modify it.

You can highlight order items but you cant bring up the ticket in the pos module where you could further view ticket info such as paid status and possibly reprint the closed orders or do voids after unlocking the ticket.

Im gonna run some tests and maybe give you some more ideas if your interested


Ahh… the Ticket Explorer Module - now I get it.

Great idea! Had not thought about that. That should be easy enough to implement!

LOL, this need some work … I need to test button colors to know what color to use for button Caption, and I see the Print Bill command is shown twice - presumably because it has 2 AMC Mappings in my system… hmm…

EDIT: got that fixed …

Let’s see about adding some defined Ticket Tags now … I don’t see a Query for that, so we’ll need a “Special Report”.


I have a few Ticket Tag Groups …

[Ticket Tag Groups:1,4,4,2,2,2,1,1,1]
 g.[Id] as [tagGroupId]
,g.[Name] as [tagGroupName]
FROM [TicketTagGroups] g
ORDER BY g.[SortOrder], g.[Name]

But only 1 Group named TA has predefined Tags, so only these Tag Buttons will appear for selection …

[Ticket Tags:1,4,1,4,2,2,2,1,1,1,1]
 t.[Id] as [tagId]
,t.[Name] as [tagName]
,g.[Id] as [tagGroupId]
,g.[Name] as [tagGroupName]
FROM [TicketTags] t
JOIN [TicketTagGroups] g on g.[Id]=t.[TicketTagGroupId]
ORDER BY g.[SortOrder], g.[Name], t.[SortOrder], t.[Name]

And there they are (they don’t function yet ;)) …


Ahhh interesting approach.
Is the purpose of the special reports basically to help with querying and inputting things from the data retrieved in the reports and feeding them into gql as so to avoid using other languages such as php?

Could we do that to possibly enable switching between departments on the POS screen as another feature to add to the pos module?


Yes, the Special Reports are to avoid use of PHP when we don’t have a GraphQL Query to get the data we want.

First incarnation used PHP (using SQL Queries) to get a lot of data we did not have access to. Then I came up with the idea of creating the Special Reports using {REPORT SQL DETAILS:X} because we have a GQL Query for getCustomReport(name:"reportName"). Just a sneaky way to run SQL Queries without needing a server-side language like PHP. :wink:

The result is more or less the same, but we can keep the system PHP-free. By avoiding PHP, using something like GQL Modules requires less setup, because we don’t need to run a site that has a PHP Engine.

Personally, I am happy running a PHP-enabled site, but I was striving to make the setup of GQL Modules as easy as possible to avoid Website configuration problems. You could run this inside SambaPOS’s lightweight Webserver if you wanted to.

Sure, why not? But I have no use for such things, so you’ll need to learn how to do that yourself :wink:

Basics first - already in place.
Ticket Note - done.
Ticket Tags (predefined) - almost done.
Switching Departments - don’t care :stuck_out_tongue_winking_eye:
Combo Setups with Grouping - good luck!


Sweet. Thanks for everything so far. It’s beautiful work, and definitely something I can use to further study everything and possibly contribute more to this project as I can see many clients who would want this feature.

I’ll try to work on the switch department and see how I can add that to the POS module.
Once I grasp the fundamentals of this, Combo Setups with Groups Here I come!

Just one more thing that make ticket tags, print commands more noticeable. Giving them headers such as you have done with Ticket Notes :wink:


Working Ticket Tags (pre-defined) and Ticket Note. This works with existing Tickets, or New Tickets…

Video shows:

  • Setting Ticket Note and Ticket Tag on New Ticket before any Order selection, then adding Orders, and Closing Ticket.

  • Opening the now-existing Ticket to change the Ticket Tag, clear the Ticket Note, and Close the Ticket.

  • Opening the Ticket again, Voiding all Orders, and Close the Ticket.


@Shivan, I’m going to give non-defined Ticket Tags a go next.

It will will require that the TagGroup is defined, but no SubTags are defined. I will use a text input field to allow the operator to set the Tag Value.

Sound good?


Sounds sweet. But a question, if a tag value is set using the text input field, and the TagGroup is set to save free tagging. Would that save the value for future?

I’m also thinking, if there is no tag group under ticket tags, then my guess is that it wont display anything under ticket tag header correct?


Not sure, we’ll see. If so, then a SubTag will become defined, and the text-input will disappear. Hmm… let’s see what happens.

It will display Ticket Tags in the header/info area that are set through Automation, whether or not they are defined. The GQL query returns all Ticket Tags that are set on a Ticket, no matter if they are defined.

If you look closely at my previous screenshots and the video, you can see a Tag named Feedback which has a value of None. That Ticket Tag is not defined in any way whatsoever; it is set by Automation instead during Ticket Created event.

We could filter out non-defined Ticket Tags if we wanted to hide them from display.


I have a new idea that will work better. The POS Module will have a config variable for Ticket Tags that you want to use - something like this in config_modules.js:

var POS_TicketTagGroups = ['TA','TagGroup2','TagGroup3'];

Those TagGroups can be defined in SambaPOS or not; it does not matter.

If they are not defined in SambaPOS, we will treat them as Free Tags so they will have a Text input box.

If they are defined in SambaPOS, we will treat them as defined in SambaPOS, whether they have defined SubTags, and/or are set for Free-Tagging. We also won’t care if there are any SambaPOS-defined SubTags. We will display the defined SubTags as buttons, and if the TagGroup is set for Free-tagging, we’ll display a Text input box as well.

We pull all SambaPOS-defined TagGroups with the Special Report. This allows us to check the TagGroup Properties such as Free-tagging, so we can decide whether or not to supply a Text input box. Hopefully SambaPOS will handle Saving Free Tags if that is selected (it probably will, but we’ll soon see).

We can allow selection of the Ticket Tags for Module-defined TagGroups (POS_TicketTagGroups), or allow Ticket Tag selection for SambaPOS-defined TagGroups, or both.

We’ll need some more Module variables to control this:

var POS_TicketTagGroupsUseModule = true;
var POS_TicketTagGroupsUseSambaPOS = false;

That ^ for example, will allow only selection of Ticket Tags which are Module-defined, and not allow selection of any SambaPOS-defined TagGroups.

While we’re at it, we can have another Module variable to hide specific TagGroups, just in case:

var POS_TicketTagsHidden = ['GCN','GCB','Payment Info'];

I think that will cover most scenarios of usage for most people.


If they are module defined does that mean that we are literally directing all tags and tag group right into the DB without the use of predefined tag groups in sambapos? With the help of the special reports of course.