Kitchen/Bar Display using Task Printer - separate displays for Food and Drink

That will cause Void problems again.

Yes! You can do that, and that was going to be my suggestion. You can define any Custom Data you want in that manner, so you can leave the Identifier alone.

Yes, thank you! Custom values defined in Task Printer Templates work fine.
and now have this all working with various Ready states showing on the ticket. Cool!

This is a useful upgrade to QMcKay’s Kitchen and Bar Display for anyone wanting to integrate the Ready state back into the ticket and table entity screens, so will share the principle below.

I am now using a JSON string for passing multiple values to the task Completed command using a new custom value defined in the template called “Context”.

The first version shown in the post above was expanded to now include a “display” element used as a switch to control the processing in a single common Task Complete Command handling rule.

My restaurant uses 4 display widgets, “Kitchen”, “KitchenPriority”, “Drinks”, and “Bar Food” and each widget uses the same Task Completed command. This new “display” parameter passed back can be understood to mean “source” or “origin”. Single display systems won’t use it, but no harm is done leaving it there.

In the template this JSON string contains all the data the processing rule might need:

(Context={"item":"{NAME}","tid":"{TICKET ID}","oid":"{ORDER ID}","ouid":"{ORDER UID}","display":"Kitchen"})
and the task Identifier is reduced to using only the Unique Order Id:

(Id={ORDER UID})
This way the Void and Gift template sections should reliably append their data to the original order card instead of sometimes creating a new card. This is a potential issue with the original KD setup because {ORDER ID} was sometimes returning zero. Strange! (Actually it shouldn’t and the original logic is quite sound, but some experiments here suggest the issue depends on the precise timing of the execution of the Ticket Closing rule which initiates the task printing. Introducing a small time delay there appears to have solved the unreliable ORDER ID issue but i wouldn’t want to rely on it.)

The Command Completed rule receives the Context JSON data in [:CommandValue] fine, and we can extract the various elements as needed for any processing using a very simple script function called “getJSONField” which is part of a handler called “sys” in my setup where i put generic helper functions.

Example usage:
{CALL:sys.getJSONField('tid','[:CommandValue]')} {CALL:sys.getJSONField('oid','[:CommandValue]')} {CALL:sys.getJSONField('ouid','[:CommandValue]')} {CALL:sys.getJSONField('display','[:CommandValue]')}
In our processing rule, we do a Load Ticket, Select Orders to select this one order, then update any order states we want using Update Order State actions, then Close Ticket.

To get a reliable Order Id for selecting the order i am using a JS function using SQL to find the matching Order using the OrderUId field.

It should be possible to also use REPORT SQL DETAILS to do the same thing, such as:
{REPORT SQL DETAILS:SELECT Id FROM Orders WHERE OrderUid='{CALL:sys.getJSONField('ouid','[:CommandValue]')}':F.Id::{0} }

But i had trouble with that syntax as there is confusion having so many nested terms using braces and quotes and my eyes keep deceiving me!

It’s worth noting that IF the Select Orders action fails to find the matching order (probably because of a syntax error in the action parameter) THEN the subsequent Update Order State action will change the state of ALL THE ORDERS on the ticket instead of only the order we were supposed to have selected. So if you see that behavior, it is because the Order Ids field in the Update Order State action is set incorrectly for whatever reason. Syntax error? Context data in the template wrong? something else?

I also noticed that the helper function JSON.parse is very intolerant to invalid JSON data causing SambaPOS to crash easily. (p.s. Actually I think any error raised in script causes the crash, so might not be a problem with JSON.parse itself but how it is used.). To prevent crashes (especially likely in the development phase) we need to check the JSON prior to calling that function, and catch any errors.

I’m using a function to do that called tryParseJSON:
function tryParseJSON (jsonString) { try { var o = JSON.parse(jsonString); if (o && typeof o === "object") { return o; } } catch (e) { } return false; };
Unlike other similar functions i found online, this function parses the JSON only once. re: discussion on stackoverflow

which is called by:

//`
// Get field data from simple JSON string
//
// need to do sanity check on the jsonData to avoid crashes on invalid KBD templates.

function getJSONField(sField,jsonData) {

if (typeof(sField)=="undefined" || sField=='') 
      return 'Invalid field name:'+sField;

if (typeof(jsonData)=="undefined" || jsonData == '')
    return 'invalid JSON';

 var oFields = tryParseJSON(jsonData);

 if (typeof(oFields)!="object")
     return 'invalid JSON!';

 var sData = oFields[sField];

 if (typeof(sData)=="undefined") 
     return 'not found: '+sField;

 return oFields[sField];

}//`

My template top section looks like:

We use different formatting for Kitchen and Bar displays because of differing native languages of staff working here in Thailand … Thai and Khmer in the kitchen, English for bar/service staff. I also separate Drinks and Bar Food on the Bar Display for clarity and prioritization of tasks.

Prior to implementing SambaPOS we used code numbers for menu items to avoid language issues, hence the use of {ITEM TAG:MenuCode} in the template.

Kitchen Display:

Bar Display:

Order state formats with color codes for courses and various state indicators:

Ticket showing ready states:

2 Likes

There are 2 potential issues which you need to be aware of when implementing this feature:

Issue 1:
To avoid exception errors when Completing multiple orders on the Kitchen Display, you need to split the processing rule into 2 stages. The first stage which receives the Task Completed command from the Task Editor must complete all it’s actions and exit before receiving the next Completion command from the KD Task Editor, otherwise you will get an exception and system abort.

These exceptions are easily avoided by executing the 2nd stage as a background process.
The 1st stage should do nothing except fire the 2nd stage using an Execute Automation Command with “Run in Background” parameter set to True.

Issue 2:
If you get an erroneous new ticket displayed after Completing a task on the Kitchen Display, this is a known limitation on multiple Department systems using custom Ticket Types. This problem will not affect simpler configurations using only one type of ticket.

Workaround (a): Navigate back to Kitchen Display at end of Task
Completed processing. The erroneous new ticket was not saved and will be abandoned.

Workaround (b): Avoid having mixed Ticket Type mappings on Entity
Screens in same Department. We can rely on Department’s default Ticket
Type in the case that we only have one Entity Screen in the Department
which needs to create tickets of a custom type. If we want to create 2
different types of tickets, fired on a Select Entity, in the same
Department, this workaround will probably fail. (not tested).

Workaround (b) is more CPU friendly than (a).


As recommended by @QMcKay:
A more efficient version of this feature would avoid the duplicate JS calls by doing all the JS calls only once and storing the returned values in Local Settings. This would be done in the Stage 2 rule which then fires Stage 3 to do the actual processing.
Stage 3 would use the Local Settings values as the action parameters. This avoids the redundant SQL query and scripts.

Philip while reading your post I decided to create grouping feature for task editor. You can’t see that as I’m releasing new features on beta group so I added you to beta. You can search for 5.1.61 topic to follow updates.

Your solution is really great. I appreciate you shared this. However imho tracking ready state out of ticket idea should also be discussed. Tickets may have their own workflow, for example you can close the ticket by settling it before all courses delivers. With new grouping feature it will be possible to group items by table so you may have better control on this.

2 Likes

If people show enough interest I will make a step by step tutorial on how to implement this.
Bear in mind also, one needs to be fully aware of other possible effects of integrating this feature into an existing system and how the state updates provided might be used as part of any workflow.

As Emre mentioned. one needs to consider situations such as what happens if a ticket is settled prior to the chef completing it, or the way various classes of cancellations are handled, etc.

I’m still refining this logic and exploring various scenarios.
The most difficult is deciding what set of conditions will determine if inventory is consumed or not.
There are various scenarios in the real world to consider:

a) the simple case is when an order is cancelled prior to it’s preparation in which case inventory shouldn’t be consumed.

b) maybe the cook started making it and then the customer cancelled. Part of the recipe was consumed, some was not. Some case is too difficult to handle while others such as 2 part recipes can be handled using order tag editing.

c) maybe the customer cancelled the order after it was completed in which case inventory was obviously consumed.

d) in a system with course scheduling, orders are not submitted to the kitchen until that course is due, so handling cancellations prior to being submitted is easy and trouble free. This is how our system operates.

e) something else? i am interested to know about any other potential problems or situations people want to handle.

I follow all tutorial steps but i thing is missing that is shown in your this picture

Rules to update KDStatus State when the Ticket is Closed
Drink

In this picture you show “KD Update Order KDStatus” two times but when i add it from actions it can be select for 1 time how you show this option 2 times.

So i deiced to leave 2nd time “KD Update Order KDStatus” in which CurrentState:BPrinting and NewState:BPrinted.

and complete all remaining steps.

after this when i go to screen and select “Design Mode” get this error.

Now please tell what have to do
Thanks

Right-click in the Action List on the LEFT and select Display all Values, then scroll to the bottom of the list to see the action again. You can repeat this as many times as necessary.

I done this step but error exist

Show screenshots for the Entity Screen Configuration.

Also, click the Detailed Report tab on that error dialog, copy all the text in the box, and paste it into the forum.

Sorry the problem with entitiy screen that was configured 2 times it was mistake sorry

after completing all steps the result is like 0. there is no something to show Display Screen

after completing all steps the result is like 0. there is no something to show Display Screen

Order State for KDStatus is not being set or updated properly, probably because of constraint.

Show the KD Rules with all Actions expanded.

Show the Product for “Special Soup”.

Show the KD Print Job Mapping.









Product Group and {GROUP CODE} are the same thing.

Your Products do not have {GROUP CODE} == Food

For example, the Product “Special Soup” has {GROUP CODE} == SOUP

Your Rules contain a Constraint that prevents the Rule from being triggered, because the Constraint specifies that the {GROUP CODE} must contain the word Food.

Instead of changing the Group Code for all your Products, you can create and use a Custom Product Tag:

Then use the Product Tag Editor to set your Food Products:

And change the Rules to use the productType Tag instead of the Group Code, like this:

Hello,
now facing 2 more error after changes according to your tutorial.

First

I set 2 “productType” Food and Beverage
now when i make order Kitchen display show only Beverage Items but Food Item is not showing. some screenshot is attaching for you please check


Second

problem is this when i make order it show on Kitchen Display but after closing Ticket by settle and pay, it exists on Kitchen Display. as shown in pictures

This setup has worked wonders for me however when I used the Printer Templates here it breaks the different food items on the order into separate task cards on my KDS, how can I stop this? For example if a customer orders 3 waffle order it will create 3 task cards for waffles instead of a single combined card.

That has to do with the Task Identifier in the Template, which is set by this line (or similar):

(Id={NAME}-{ORDER UID})

You can choose to set the Task Id in any way you see fit, using other Printer Template Tags such as:

{NAME}
{TICKET ID}
{TICKET NO}
{ORDER ID}
{ORDER NO}
{ORDER UID}

Use a combination of tags to set the Task Identifier for what works for you.

The reason it would break the Order into multiple Tasks would be caused mainly by using {ORDER UID}. That Tag is unique to each Order, no matter the Quantity.

On the other hand, the other Tags recommended in that list are not unique to an Order. For example, the Order Id and Order Number are unique to an Order Line, or multiple Orders that are submitted at the same time, which is why you will probably want to combine the it with the Order Name, such as:

(Id={NAME}-{ORDER ID})

That ^ would set a Task Identifier as being something like Waffle-794, indicating any Quantity of Waffles (ie. 3) that were submitted at the same time, which will be identified by the {ORDER ID}. In this way, the Task Card would show something like this:

3 Waffles

So if that is what you prefer, then change your Id definition in the Template. But be aware that this might cause other unwanted behavior, especially having to do with VOIDs in that you will not be able to VOID 1 Waffle out of the 3, because the Identifier has no uniqueness to a specific Order of Waffles - it has no way to distinguish the difference between the 3 Waffles.

It might also help to set the Merge Lines setting in the Template:


Even using the Identifier (Id={NAME}-{ORDER UID}) with Don't Merge set in the Template produces KD Task Cards in two different ways, depending on how you submit the Order …

Show the Order Added and Ticket Closing Rules for the Food items, something like this:

It might also help to remove the Product Group Mappings from the Print Jobs, and use the Product Tag instead, like this:

I tried to implement this system but encounter a strange issue. In my system, the {ORDER UID} changed with the order is voided:

The second (red card) is the voided of the first card. I used (Id={NAME}-{ORDER UID}) as suggested in this tutorial. Is there any reason why the ORDER UID would be changed? I upgraded this dababase from V4, though I doubt that has anything to do with this.