Age Check for selling drinks

In this tutorial I’ll show you how to implement a Age Check mechanism that is required to sell alcoholic drinks in some countries.

:warning: Important

  • Install at least 4.1.61 version before implementing this tutorial.
  • For simplicity I’ll skip Rule Mapping Steps. While creating a rule don’t forget to add rule map.

###Preparing Products and Tickets

I’ll start by configuring a custom product tag named Confirm Age.

After Saving it edit your products and set Confirm Age tag to True for all products that needs Age Checking. For this tutorial I’ll enable it for all Beverages.

I’ll create a new Update Ticket Stateaction to mark Ticket as Unconfirmed that will work when I first add a product that needs age checking.

Note: I’ll prefix all Age Check related rules and actions with AC_ to differ them from other rules and actions.

I’ll create another one to update Ticket’s Age Check state to Confirmed. That will work when Customer’s age gets confirmed.

Now I’ll create a rule to see how it works. I want to change Ticket as Unconfirmed when a beverage added.

When a new order added… if added item needs Age Checking and ticket is not already confirmed it marks ticket as unconfirmed.

Now we can test how it works. When I add a beverage ticket’s Age Check state should become Unconfirmed.

When I add the first order nothing happens but when I add Coffee Age Check state becomes Unconfirmed. Remember for this sample I’ve enabled age check for only beverages.

If it works fine we can continue our implementation. Cancel added orders and close ticket.

###Asking Customer Birthday.

On this step I’ll create a new dialog to ask Customer’s birthday and save it as a ticket tag. I’ll start by creating a new Ticket Tag configuration.

I’ve named it as Customer Birthday. Note it somewhere because we’ll read it’s value by using that name. The important setting is Tagging Type. Set it as Date. I’ll leave sub tags and mappings empty.

I’ll create an action to set this Ticket Tag.

When I set a Birthday value and execute this action it saves birthday as a ticket tag.

Now I’ll go back to AC_Mark Ticket as Unconfirmed when Age Check required item added rule and edit it to add this action.

Instead of setting a static Birthday value I’ve used Parameter Query feature to display a dialog box that allows operator enter a birthday.

You can get more info about that from…

So when this action executes it will ask birthday and save entered value as a ticket tag. Let’s test it.

When I add a beverage this screen will appear. We’ll format it better but for now I can type anything here.

When I type a date and click OK it will appear as a ticket tag.

On next steps we’ll test this value and execute related actions.

It would be nice if we had a rule that called Customer Birthday Updated so we can use constraints to check if customer’s age is 18 or not. This is one of the less known features of automation system but we can do it with Execute Automation Command action. Cancel order, close ticket and create a new Execute Automation Command action.

When that action executes it triggers Automation Command Executed rule so I can create rules that handles that event. On final step of AC_Mark Ticket as Unconfirmed when Age Check required item added rule I’ll execute this action.

To sum it up AC_Mark Ticket as Unconfirmed when Age Check required item added rule…

  • Checks
  • If added order needs age checking.
  • If ticket is not already confirmed.
  • Does
  • Marks ticket as unconfirmed.
  • Asks Customer Birthday.
  • Saves it as a ticket tag.
  • Executes a notification about customer birthday updated.

###Validating Customer Birthday

When operator inputs a customer birthday Customer Birthday Updated command executes. On this step we’ll create rules to handle that event.

We need to update order’s Confirmation state as Confirmed/Unconfirmed if age validates or not. That allows us to create reports about that orders. So before validating birthday we’ll create actions to update order states.

This action will update order’s ACStatus as Unconfirmed

… and this one will update it as Confirmed.

:bulb: Advanced users can create a single action and use variables to update order state. I’m creating separate actions to visualize workflow better.

####Rule for valid age

We’ll create a rule that checks if customer is older than 18 yrs and executes related actions.

I’ll explain constraints in more detail.

  • Automation Command Name : You’ll remember we executed a notification called Customer Birthday Updated. That constraint checks if we’re handling correct notification. In other words we’re handling Customer Birthday Updated automation command.
  • [=ADM('{TICKET TAG:Customer Birthday}',216)] : This expression adds 216 months (18 years) to customer birthday and checks if it is Before current date. We’re reading customer birthday with {TICKET TAG:Customer Birthday} tag and add 216 Months to birthday with ADM function. If you’re age limit is different than 18 you can change 216 value with related months. You’ll multiply age with 12.
  • {TICKET TAG:Customer Birthday}. This constraint checks if a birthday entered or not.

When it validates rule updates Ticket and related order as Confirmed .

####Rule for invalid age

Previous rule executes if customer age is valid. We’ll create another rule that handles Customer Birthday Update event and works if customer age is not valid.

Notice how second constraint checks if calculated date is after current date. If it is after that means customer is younger than 18.

If customer age is not valid it marks order as Unconfirmed. It also does two things.

  • Update Order is a built in action that comes with default install. We’ll use it to exclude order from calculation like we do for gifts or voids.
  • Update Order Status is also a built in action. We’ll use it to prevent order from printing to kitchen. We’ll simply clear status so New status will disappear but to fit that to your work flow you can define a custom state for it.

This is the expanded configuration for these actions.

If you’ll allow operator to enter empty values in birthday asking dialog we also need a third rule to handle that case. You can clone it from AC_Update Ticket if Age Check invalid rule and adjust constraints as it does the same thing.

Let’s test how it works.

####Case 1

I’ll add a beverage and enter 11 11 1970 as birthday.

  • Ticket’s Age Check status becomes Confirmed.
  • Order’s status becomes Confirmed.
  • Ticket Tag updates to save Customer’s birthday.
  • Adding more beverages does not ask age anymore.

####Case 2

I’ll create another ticket, add a beverage and enter 11 11 1999 as birthday.

  • Ticket’s Age Check status remains Unconfirmed.
  • Order’s status becomes Unconfirmed.
  • Order’s New status cleared so it won’t print to kitchen.
  • Order is not included in ticket amount and it does not decrease inventory.
  • Adding new beverages will ask Birthday again.

###Formatting Birthday Asking Dialog

You’ll notice you can enter any value as birthday. On this step we’ll improve that dialog.

You’ll remember the syntax that triggers the dialog was [?Enter Customer Birthday].

We can change how that dialog works. The general customization syntax is…

[?<parameter name>;<mask>;<default value>;<settings>]

You can define a regular expression to mask the input. This regular expression can be used for date entry.

([1-9]|10|11|12) (0?[1-9]|[12]\d|30|31) \d{2}\d{2}?

It has three parts. First part allows values from 1-9 or 10 or 11 or 12. This part formats month part. Second part formats day part. It allows numbers from 1 to 31 and also single digit days that starts with 0. Third part allows 2 or 4 digit years. When we include that mask the syntax becomes…

[?Enter Customer Birthday;([1-9]|10|11|12) (0?[1-9]|[12]\d|30|31) \d{2}\d{2}?]

:bulb: Good to know
; character separates parameter name and mask. If you need to use ; character in mask or somewhere else you can define a different character as separator. SambaPOS recognizes first punctuation character as separator. So using it as [parameter#mask] will mean you’re using # character as separator.

()"'/\=?! characters are reserved for title and can not be used as a separator.

We can set a default value for birthday. For example you can use {TICKET TAG:Customer Birthday} tag as default value so previous unconfirmed birthday appears on additional confirmations. If you don’t want to include a default value but configure a setting just skip it by adding an additional separator.


The last part of the syntax is used for setting. Settings are single character flags that enables, disables some features.

  • O: Displays OK button.
  • C Displays Cancel button.
  • N Displays Numeric keyboard.
  • S Displays Alphanumeric keyboard.

I want to show OK button, hide Cancel button and display a Numeric Keyboard. So the needed setting is ON and the resulting syntax is…

[?Enter Customer Birthday;([1-9]|10|11|12) (0?[1-9]|[12]\d|30|31) \d{2}\d{2}?;;ON]

Notice we’ve skipped default value with double ;; characters. To complete this sample I’ll also include a default value.

[?Enter Customer Birthday;([1-9]|10|11|12) (0?[1-9]|[12]\d|30|31) \d{2}\d{2}?;{TICKET TAG:Customer Birthday};ON]

Now I’ll update rule and change parameter as …

This is the resulting Birthday Asking Dialog :slight_smile:

  • Numeric Keyboard appeared.
  • Cancel button removed.
  • Entered value gets automatically formatted as date.

:bulb: Good to know
You’ll notice it forces operator to enter a date. However a customer may change his mind won’t tell his birthday. If you want to allow empty values you can surround mask as (<mask>)? Doing it will allow empty values. Otherwise operator should enter a birthday. When surrounded mask becomes

(([1-9]|10|11|12) (0?[1-9]|[12]\d|30|31) \d{2}\d{2}?)?

You’ll remember we handled empty birthday value case with AC_Update Ticket if no birthday entered rule.


If you have Custom Reports module you can list unconfirmed tickets with that template.

[Unconfirmed Tickets:2,2,2,2,1]
>Ticket No|Date|Time|Birthday|-
{REPORT TICKET DETAILS:TT.Customer Birthday:(TS Age Check=Unconfirmed)}

That appears as…


Ive got as far as the keyboard appearing to enter the customers birthday but it automatically adds the letter O and i cannot edit or type anything in

then if i just press ok it shows the letter B in the ticket tag (not even the letter O that the keyboard screen already had in it)

how to i fix this so i can type in the keyboard? ive checked all the previous steps and i cant see where i have gone wrong

Is your prompt exactly one of the following?

[?Enter Customer Birthday;([1-9]|10|11|12) (0?[1-9]|[12]\d|30|31) \d{2}\d{2}?;;ON]


[?Enter Customer Birthday;([1-9]|10|11|12) (0?[1-9]|[12]\d|30|31) \d{2}\d{2}?;{TICKET TAG:Customer Birthday};ON]

Are you using v4.1.61 ?


i fixed it, where the keyboard appears and it says “Enter Customer’s D” (that should day D.O.B) because i typed the full stops inbwteen D, O and B it kept the D then moved the O into where i needed to type the date of birth, then when pressing ok it moved the B onto the ticket tag.

Ive removed the full stops so it reads DOB and this fixed the issue as below

However i have a new problem ill post screen shots now

can you post your expression your using?

ive added my age restricted product and keyboard appeared to enter birthday, as in @emre example i enter date 11/11/1970.

  • Age Check Status should become confirmed - IT DOES
  • Order Status should be comfirmed - IT DOESNT MINE SAYS “Unconfirmed, New”

ive checked the implementation so far and cant see where i went wrong

And the reverse happens when entering a birthday younger than 18 years

  • Age Check status should become unconfirmed - IT DOESNT MINE STILL SAYS “Confirmed”
  • Order Status should be unconfirmed - IT DOES (but still shows “new”, emre’s example doesnt have “new”)

not sure what ive done for those values to be wrong?

New is part of Ticket Closing Rule. It does not actually affect this tutorials ability to work so you can ignore that state its fine. Something else is wrong with your setup. Since it deals with states which can be complicated to understand we need to see what you have done… and if you have modified any states for anything else?

Post your rule/actions that contains those state changes will help us identify the issue.

these are all the rules and actions from the tutorial that emre did, im pretty sure ive done them right (although i cant have as its not working) i cant see what ive done wrong, second pair of eyes is always welcome :slight_smile:



When you rename Customer Birthday tag you should also rename reference from age checking expressions.

ive made those changes but it still doesnt work

@RickH obviously one of the invalidation rules incorrectly executes after validation. Please double check invalid and empty birthday handling rule constraints.

ive got invalid working now so when age entered is under 18 yrs i get:
So this ones appears to be working?

if i leave the keypad blank and do not enter a birthday i get the same result as above without the ticket tag as no birthday was entered
so this appears to be correct also?

If birthday entered is over 18 years old

@Emre ill check your suggestions now, thanks :slight_smile:

@Emre these are my Valid, invalid and no birthday entered Rules, can you spot my error? From my last screenshots invalid and no birthday selected seem to be working? i cant figure out why valid isnt



No birthday entered

Also i dont want to show the OK button on the keypad as the ENTER button seems to just do the same thing, however when following your guide below it says that O displays the OK button. I have removed this so I only have N for numeric keypad but the OK button still shows even when it is set not too? is this a bug?


The last part of the syntax is used for setting. Settings are single character flags that enables, disables some features.

O: Displays OK button.
C Displays Cancel button.
N Displays Numeric keyboard.
S Displays Alphanumeric keyboard.
I want to show OK button, hide Cancel button and display a Numeric Keyboard. So the needed setting is ON and the resulting syntax is…

[?Enter Customer Birthday;([1-9]|10|11|12) (0?[1-9]|[12]\d|30|31) \d{2}\d{2}?;;ON]

Notice we’ve skipped default value with double ;; characters. To complete this sample I’ll also include a default value.

[?Enter Customer Birthday;([1-9]|10|11|12) (0?[1-9]|[12]\d|30|31) \d{2}\d{2}?;{TICKET TAG:Customer Birthday};ON]

I thought you changed D.O.B to DOB. Your Rule Constraints should be changed too, no?

i fixed it, some of my {TICKET TAG:X} had Customers’s D.O.B instead of Customer’s D.O.B (theres an extra ‘s’ in the first example. its now all working woooo :smile:

@QMcKay the D.O.B to DOB only affected the text that displays on the keyboard/keypad

Do we know if we can disable the OK button on the keypad? ive removed the setting of ‘O’ but the OK button still shows. As it does the same as the ENTER button on the keypad i just wanted to remove it

Ive tried Adding and removing ‘C’ and the cancel button does appear and disappear but OK is always showing even when the setting isnt there to activate it

1 Like

@emre in your example once age has been verified it does not ask again for the next items that are added. Mine is asking after every item even when the first one is confirmed, where do i need to look/what have i done for this to stop asking when first item is confirmed?

next item added and keypad appears again asking for age (automatically saved in keypad so can just press enter, but this shouldnt show at all?)

Check order added to ticket rule constraint correctly checks Age Verification state.

thanks for pointing me to the right place, i fixed it :slight_smile:


sorry, i have another question…

If the customer is clearly old enough to purchase age restricted items we would never ask them for proof of ID as its pretty obvious they are old enough. How could i bypass having to enter a birthday. So id want the ticket and order to show as confirmed but i wouldnt be entering a birthday.

I like what you did with leaving it OK/ENTER to unconfirm the sale, so can i set a constraint so that if i entered (a code) for example 99 when the keypad asks for the birthday it would mark the sale as confirmed? I thought of this then realised whatever is entered has to be in the date format set so it would need to be 9999 or 999999.

is there a way to do this?