Action to set Ticket {NOTE}

I am trying to clone one ticket it to a new one, but when I do the ticket {NOTE} is lost.

Before cloning the ticker, I can store the {NOTE} as a Program Setting and then create a new ticket with a Ticket Tag called “TicketNote” - But this isn’t really the same. The editing method for the note is different, and it won’t work with any pre-existing printer tags (I would have to create new tags for what should really be the same thing).

Is there any way for us to manually set the ticket note?

Execute ticket command action has a edit ticket note command…

1 Like

Awesome - Thanks @JTRTech

Ahhh… But how do I actually use this to set the note - I would expect the action to accept the value that I want to set?..

Never used, would have expected it was going to work like any other action …

It doesn’t look like it???

@QMcKay - Do you have any idea how to use the Execute Ticket Command action to set a ticket note?

M

There is no Action to set the Ticket Note programatically. The Action that is available only invokes the Ticket Note Editor window.

It could be done now though via GraphQL and some JScript. Would need to look into the exact details, but it would probably involve opening the Ticket, setting the Note, and closing it. I am sure it is possible.

The ticket will be open anyway, so that wouldn’t be too much of a problem. All I’m trying to do is to clone a ticket including any ticket note.

In GQL you need to:

  • Register Terminal
  • Load Terminal Ticket
  • Update Terminal Ticket (Note)
  • Close Terminal Ticket

I cannot give details now as my main laptop is not with me.

You could also do it with SQL in JScript, but yeah.

It would be nice if the Clone Ticket Action actually cloned the Note as well. Make that a feature Request.

Yeah, I have only just started to get my head around standard Rules and Actions. I want to actually go live before I start trying to hve to work out more about what I can to with Scripting or GQL! :slight_smile:

I’ll make the feature request now.

##Script

NOTE: the function updateTerminalTicket is stripped down for simplicity to include only the Ticket Note, without the Ticket Tags nor Ticket States because Tags and States would require passing and handling Arrays, though it could be done with some extra code.

Name: GraphQL
Handler: GQL
Script:

// main GraphQL Execute Function
function gqlEXEC(query, callback) {
	//return query;
    var data = gql.Exec(query);  // returns JSON as String
    var dobj = JSON.parse(data); // converts JSON String to Object
    return data;
};

function registerTerminal(terminal,department,ticketType,user) {
    //returns unique terminalId like: 7rO2ngxHRE2Rs47kHlBT8A
    return 'mutation m {terminalId:registerTerminal(terminal:"'+terminal+'",department:"'+department+'",ticketType:"'+ticketType+'",user:"'+user+'")}';
};
function unregisterTerminal(terminalId) {
    return 'mutation m {isTerminalUnregistered:unregisterTerminal(terminalId:"'+terminalId+'")}';
};
function getTerminalExists(terminalId) {
    return '{isTerminalExists:getTerminalExists(terminalId:"'+terminalId+'")}';
};

function terminalTicketDetails() {
    return '{id,uid,type,number,date,totalAmount,remainingAmount,note,entities{typeId,type,id,name},states{stateName,state},tags{tagName,tag},orders{id,uid,name,quantity,productId,portion,price,priceTag,calculatePrice,locked,decreaseInventory,increaseInventory,states{stateName,state,stateValue},tags{tagName,tag,quantity,price,rate,userId}}}';
};
function loadTerminalTicket(terminalId,ticketId) {
    return 'mutation m {terminalTicket:loadTerminalTicket(terminalId:"'+terminalId+'",ticketId:"'+ticketId+'")'+terminalTicketDetails()+'}';
};
function updateTerminalTicket(terminalId,note,tags,states) {
    return 'mutation m {terminalTicket:updateTerminalTicket(terminalId:"'+terminalId+'",note:"'+note+'")'+terminalTicketDetails()+'}';
};
function closeTerminalTicket(terminalId) {
    return 'mutation m {closeTerminalTicket(terminalId:"'+terminalId+'")}';
};

function updateTicket(ticketId,ticketNote,ticketTags,ticketStates) {
	var terminal = gqlEXEC(registerTerminal("Server","Restaurant","Ticket","Admin"));
		terminal = JSON.parse(terminal);
	var terminalId = terminal.data.terminalId;
	
	var ticket = gqlEXEC(loadTerminalTicket(terminalId,ticketId));
		ticket = JSON.parse(ticket);
		ticket = ticket.data.terminalTicket;
	
	var note = typeof ticketNote === 'undefined' || ticketNote=='' ? ticket.note : ticketNote;
	var tags = typeof ticketTags === 'undefined' || ticketTags=='' ? ticket.tags : ticketTags;
	var states = typeof ticketStates === 'undefined' || ticketStates=='' ? ticket.states : ticketStates;
	
	var updatedTicket = gqlEXEC(updateTerminalTicket(terminalId,note,tags,states));
	
	var closeTicket = gqlEXEC(closeTerminalTicket(terminalId));
	
	var terminal = gqlEXEC(unregisterTerminal(terminalId));
	
	return 0;
};


##Sample Call

// {CALL:X} tag
{CALL:GQL.updateTicket(ticketId,note)}
{CALL:GQL.updateTicket(40073,"test")}

// Execute Script Action
GQL.updateTicket(ticketId,note)
GQL.updateTicket(40073,"test")

1 Like

Yea you make it look so easy :smirk: (<- wanted the "roll eyes face but this will do lol).

Yeah, I’ll try and see if I can just add this to scripts without really trying to understand it for now.

Getting my head around GQL is going to have to be a phase 2 thing for me!

My GQL Modules project is all Javascript and GraphQL, which I worked on and learned since the introduction of GQL in SambaPOS… what, a year ago? So I am quite well versed in it now. Learned a lot about JS itself with that project, since before that all I did was PHP on the Web side of things.

Not sure how many people are using GQL Modules, but I use it daily and it has become a great tool for me in my day-to-day process. The Kitchen Display and Timeclock Modules have become a necessity, and the Reports Module is so easy to use for viewing things remotely to see how my Venues are performing. I am rather proud of it, even if I am a bit of a “hack” coder :stuck_out_tongue_winking_eye:

GQL Modules even has a fully working POS module that I have used from time to time, though not used it in real production on a daily basis… not sure why LOL… I need to find some more cheap 10" Tablets.

GraphQL and Javascript really isn’t that complex, and fairly easy to get a grasp of it after a short time experimenting. @emre has given us an extremely powerful tool with GQL… it really opened up the possibilities like never before seen with SambaPOS… revolutionary IMO.

2 Likes

I was daugnted by scripts at first and before making the PMS intergration had NEVER touched java/jscipt or even php, had only ever done html and css adjustments to premade packages/programs.
Although with a fair bit of initial help from Q and Kendash I would now confidently take on almost any script based challange - although with allot of googleling to check functions etc.
I sometimes find myself using scripts for things amba can do itself in expressions just because I quite like scripts power.
Although have yet to dabble too deeply at graph purly for lack of spare time with attention being else where.
Scripts are definatly a very valuble side of samba and jscript which is pretty much the same as java on a whole is a good code to have a base understanding of.

It’s been a steep but enjoyable learning curve for me. But I’m getting really close to the my final system ready to unleash on my dive shop. Can’t wait to show you guys once it’s finally completed!

1 Like

I was thinking about this some more, and realized that if this is run within SambaPOS (instead of remotely through Browser App), then there should be no reason to use/register Terminal or use terminalTicket mutation.

There are other GQL functions available to use when we want to execute GQL from a Terminal that is running SambaPOS. I need to have another look at this… it should simplify things a bit. For example:

{addTicket(ticket:{type:"",department:"",terminal:"",user:"",note:"",orders:[],states:[],tags:[],entities:[],calculations:[]}){id,uid,type,number,note,date,totalAmount,remainingAmount}}

{getTicket(id){id,uid,type,number,note,date,totalAmount,remainingAmount,...}}

{updateTicket(ticketId:0,ticketTypeName:"",note:"",userName:""){id,uid,type,number,note,date,totalAmount,remainingAmount}}
2 Likes

That was easy :wink:

##Script

Name: GraphQL
Handler: GQL
Script:

// main GraphQL Execute Function
function gqlEXEC(query, callback) {
	//return query;
    var data = gql.Exec(query);  // returns JSON as String
    var dobj = JSON.parse(data); // converts JSON String to Object
    return data;
};

function ticketDetails() {
    return '{id,uid,type,number,date,totalAmount,remainingAmount,note,entities{typeId,type,id,name},states{stateName,state},tags{tagName,tag},orders{id,uid,name,quantity,productId,portion,price,priceTag,calculatePrice,locked,decreaseInventory,increaseInventory,states{stateName,state,stateValue},tags{tagName,tag,quantity,price,rate,userId}}}';
};
function getTicket(ticketId) {
    return '{ticket:getTicket(id:'+ticketId+')'+ticketDetails()+'}';
};
function updateTicket(ticketId,ticketType,ticketNote,ticketTags,ticketStates,orderStates,orders) {
    //return 'mutation m {ticket:updateTicket(ticketId:'+ticketId+',ticketTypeName:"'+ticketType+'",note:"'+ticketNote+'",userName:"'+userName+'")'+ticketDetails()+'}';
    return 'mutation m {ticket:updateTicket(ticketId:'+ticketId+',ticketTypeName:"'+ticketType+'",note:"'+ticketNote+'")'+ticketDetails()+'}';
};


function updateTicketDetails(ticketId,ticketNote,ticketType,ticketTags,ticketStates) {
	var ticket = gqlEXEC(getTicket(ticketId));
		ticket = JSON.parse(ticket);
		ticket = ticket.data.ticket;
	
	var type = typeof ticketType === 'undefined' || ticketType=='' ? ticket.type : ticketType;
	//var user = typeof userName === 'undefined' || userName=='' ? ticket.type : userName;
	var note = typeof ticketNote === 'undefined' || ticketNote=='' ? ticket.note : ticketNote;
		note = note==null ? '' : note;
	var tags = typeof ticketTags === 'undefined' || ticketTags=='' ? ticket.tags : ticketTags;
	var states = typeof ticketStates === 'undefined' || ticketStates=='' ? ticket.states : ticketStates;
	
	var updatedTicket = gqlEXEC(updateTicket(ticketId,type,note,tags,states));
	
	return updatedTicket;

	return 0;
};

##Sample Calls

// parameters
GQL.updateTicketDetails(ticketId,"ticket note")

// set a Note
GQL.updateTicketDetails(40075,"test note")

// clear a Note
GQL.updateTicketDetails(40075,null)

Thanks @QMcKay, I managed to get this working today. I had a few issues with timing…

Most of my cloning automcation commands take place by storing values as program settings and then updating a newly created and opened ticket (kind of while the ticket is open os screen). But I had issues when trying to update the ticket note using this GQL method while the ticket was open. Instead, I could only get reliable results when the ticket wasn’t currently open. At some stage when setting the note while the ticket was open I got the message: “Ticket changed. Your latest changes not saved.”

To get this to work and change the ticket type this is what I had to do…

  1. Open ticket I want to clone
  2. Create program settings for:
  • Ticket Note
  • Ticket Tags
  1. Create the new ticket via cloning
  2. Set the ticket type for the new ticket
  3. Close the new ticket so next time it opens it has the correct buttons and menu
  • As this ticket closes, use a rule to catch the TICKET ID of this new ticket
  1. Execute a “Set note” rule
  • This rule applies the ticket note using GQL as described above. This occurs while the ticket closed
  1. Execute a "Load and tag rule
  • This rule…
    • Opens the new ticket using the TICKET ID that was caught above on closing
    • Applies ticket tags using the values stored in program settings back in step 2

So it’s not pretty, but it seems to be working reliably…

I agree, not pretty. Would be nice if the Clone Ticket action did all of that for us. Too bad it currently does not, so it is not a TRUE clone. But at least there is a workaround for now.

1 Like