Script variables consist of an internal polymorphic value. This means that a variable can be declared in one form, but change to other forms as required. There are a number of internal data types, which define the way variables are stored internally, and there is also a range of commands to create variables of certain types.
Visual Basic Users will find that script variables behave like Variant datatypes in many respects. While they are not simply variants in the VB sense, they have similar morphic abilities.
Variables are created by using the set command, in the form:
set var = expression
Where expression can be taken from the table below.
|price(??)||Create a variable that holds a monetary amount.|
|money(??)||A synonym for price()|
|saleline()||Retrievs fields and information about a single saleline|
|total(...)||Return the total of an attribute across all salelines. Typically used to return the total quantity of an item in the sale|
|float()||A variable that holds a floating point number.|
|string()||A variable of type string.|
|date()||Loads a variable with a date, either absolute or relative, or POS data related.|
|symbol()||Create a variable based on an indexed variable name. This expression is used to ensure that symbol subsitution occurs in the correct order when used nested variables in symbol names.|
|timespan()||Create a variable that holds an interval of time.|
|object(sub-object)||Create a complex variable, such as a complete sale, product, or an interface to items such as printers and system files.|
|config()||Returns a true/false value based on system wide setup checks. This includes POS configuration options, database setup and file presence.|
|tax()||Calculate the tax in or on a price, where the tax calculation can be performed against a random price value.|
|chart()||Creates a single chart, where script creates an image at runtime.|
|filter()||Creates a filter object used to restrict or manipulate AlixData object streams.|
|function()||Applies a function to a variable, where the function applied depends on the underlying variable type. This is typically used to access variable specific requirements.|
|right()||Returns the rightmost N characters of a string variable.|
|left()||Returns the leftmost N characters of a string variable.|
|mid()||Returns a substring based on characters inside a string|
|length()||Returns the length in characters of a string variable.|
Internal Data Types
- Number Signed 64 bit number.
- Float A floating point number able to hold numbers to 6 decimal places
- String Text String. Length limited by machine memory
- Money Holds currency amounts
- Date An absolute date and time
- Time A time value
- TimeSpan A time interval, such as 3 hours 42 minutes
- Null An internal representation. Does not represent SQL null value
- Special A range of special purpose value representations. For example the is(odd) condition is held in a special variable class
- Boolean A Yes/No or True/False value.
- AlixData A stream of data, such as a file or a SQL cursor, supplied using Alix Protocols
- Array An array of other datatypes, such as an array of strings.
- Chart A linked variable that generates chart/graphs in JPEG format for display.
Datatypes can be converted from one type to another using the convert command.
An alternative form using the price() keyword, which is a direct synonym. The amount-text string can be any valid price string, valid for the current country configuration.
set s = money(2.34)
This results in the variable s, having the value: $ 2-34
String variables can contain up to 16,000 characters.
An alternative form using the string() keyword is to use quoted strings. When using quoted strings, the POS detects if the first character is quotation marks ("), and if so, removes the trailing quotation mark also if present. Using this technique, it is not necessary to double-quote in strings themselves to obtain quote marks.
set s = "Hello, "Mum", How are you?
This results in the variable s, having the value: Hello, "Mum", How are you?
|now||The current local system time.|
|empty||Equivalent to date(now)|
|start of month||The date/time at the beginning of the month|
|start of year||The date/time at the beginning of the calendar year|
|yesterday||The date yesterday, with the time set to 00:00. For example, if the current date/time is 24-june-2000 10:14, then date(yesterday) will be 23-june-2000 00:00|
|today||The date and time of the start of today. (Midnight this morning).|
|One of: monday tuesday wednesday thursday friday saturday sunday||The date and time at the previous day selected. For example, if today is friday and you request date(thursday) the time is set to yesterday morning. If you request date(friday) then the time is set to the beginning of the current day.|
|shift-N||For systems with shift handling, returns the date/time of the start of the Nth shift previously. The value date(shift-0) returns the opening time of the current shift, the value date(shift-1) returns the opening time of the previous shift, and the pattern continues. If the value of N exceeds the number of shift records, then the oldest starting shift date/time is returned.|
|other values||Are assumed to be literal dates/times. Using this form is not generally recommended as the method of parsing literal dates is machine specific.|
When keywords are used, the POS first removes any whitespace and converts them to lowercase. This means that Start OF MONTH is equivalent to startofmonth
set now = date(now)
set yesterday = date(yesterday)
set lastclosedshift = date(shift-1)
set now = date(now)
set adjust = timespan(15,0,0,0)
set day17ago = now - adjust
timespan(days , hours , minutes , seconds)
- The whole number of days to include in this span. Should be 0 or greater to create an absolute timespan, that is a fixed period of time. A negative value in the days argument is used to create relative timespans.
- The whole number of hours, between 0 and 23 inclusive.
- The whole number of minutes, between 0 and 59 inclusive.
- The whole number of seconds, between 0 and 59 inclusive.
If the days argument has a value of -1, (minus one), then the timespan created is equal to the period of time (days only) since the beginning of the month. For example, on the 20th of the month, the value of timespan(-1,2,3,4) will be 19 days, 2 hours 3 minutes and 4 seconds. This timespan can be useful when analysing data and working out statistics.
If the days argument has a value of -2, (minus two), then the timespan created is equal to the period of time (days only) since the beginning of the week, where Sunday is day number 1. For example, on tuesday, value of timespan(-2,3,4,5) will be 2 days, 3 hours, 4 minutes and 5 seconds. The same variable on thursday will be 4 days, 3 hours, 4 minutes and 5 seconds. This ability can be useful when writing reports which need to run from the start of the week or some other aribitary date position. By adding or subtracting these timespan values from the date(now) variable, you can achieve any date. eg:
set now = date(now)
set days = timespan(-2,0,0,0)
set startofweek = now - days
The total() expression calculates the total across salelines and returns a single value
set answer = total(args)
The args parameter controls what total is required, the valid options are:
set x = total(pid(16)) set y = total(pid(20,22,27))
The following example shows how you might like to block accepting payments if the total quantity of pid 300 is greater than pid 408
Edit custom.pscr This file handles events that the pos generates. We are going to change event #1025 (Sale Payments Allowed) which is called before any payment is applied to a sale to allow customisation scripts to deny certain payment types.
:event(number(1025) index(0)) set x = total(pid(300)) set y = total(pid(408)) if x > y then message(99,1,You cannot sell more X than Y. [X=%x%, Y=%y%]) return 0 endif return 1
Note the return 0 in the failure path. This tells the POS Engine not to apply this payment.
If you are using payment types such as Eftpos, this event is fired AFTER the payment has been taken from the customer but BEFORE it is applied to the sale. So returning 0 to not apply the payment is not wise as the customers payment will go into scripting limbo. If these cases you are better to call the above script before starting the payment.
A sample button being blocked if quantity of pid 300 > pid 408
button define at(10,205,197,245) brgb(223,253,179) label(Eftpos) keys(+Ee) legend(label(E) at(5,5) font(arial,16)) font(arial,22) if(cond(total(pid(300)) > total(pid(400))) then(position(disable) rgb(255,255,255) brgb(98,99,92))) hook(20200) execute eftpos(go) end
The saleline() expression retrieves a single field from a saleline
set answer = saleline(Selector, Field)
The Selector parameter controls which saleline is used. A value of -1 uses the current working saleline and is the most common selector used. Values 0,1,2... return the zero based saleline on the sale. Eg saleline(1,unitprice) returns the second saleline on the sale
The Field parameter identifes the field to be returned.
set x = saleline(-1,piditem) set y = saleline(-1,quantity)
The Field values that can be returned are: (List is in order of evaluation)
|if()||Conditional retrieval. Not yet fully documented|
|unitpricefromtotalprice||P1947||Total price divided by number of items. Designed for unit based items only|
|price.*||P1910||Direct access to internal price calculation information|
|discounttotal||Total value of line discounts|
|discounttotalblank||P1652||Same information as discounttotal, but zero is suppressed and returned as an empty string|
|discountcount||Number of discounts present|
|quantity or qty||Quantity of item, in measurement units|
|quantityunit||Quantity of item, including unit of measure if not unit based.|
eg. 2 units will return "2"
|totalprice||Total price charged|
|ticketprice||The list retail price of the item. This is the price that would typically show on shelf labels|
|totalpricemod||P1590||Total price, including uplifts from modifier salelines attached to this product. Commonly seen in a coffee shop environment, where this price will include the price of the coffee and any adjustments applied through uplifts/upsell. Modifiers are not restricted to coffee and can be used for any salelines|
|unitprice||Current unit price for this item|
|unitpriceextax||P1804||Current unit price exclusive of tax|
|unitpricemod||P1603||Unit price of item and all attached modifiers. See totalpricemod above for more information|
|hiredue||Date this item is due back. Hire configurations only|
|modifiercodes||List of short codes that apply to the attached modifiers.|
|fashion-*||Reserved for fashion handling. Not documented.|
|paymentallocation||P1811||Amount of payments specifically allocated to this saleline. Payment allocation is a manual operation, generally used when selling large ticket items and the customer is permitted partial deliveries as items are paid for|
|Saleline fields that have technical names|
|work.*||Access to any Post Work information related to this saleline. Post Work is used where an item may require action before delivery to customer, such as servicing or manufacture.|
|appo.*||AppObjs. Direct access to internal related structures. Not yet documented|
|Any value that can be returned from Product|
|Any field that directly matches the table salelines. Using this form can be performance impacting|
Object Types can be any of the following, each of which has it's own list of creation arguments:
|product||Create a product variable. A single variable embodies a complete product from the database.|
|customer||Create a customer variable based on an existing customer in the database.|
|account||Create an account variable, based on an existing account in the database.|
|settle||Create a variable which holds analysed summaries of sales.|
|sale||Create a variable that holds all the details of an existing sale.|
|_filter||Reserved. Do not use.|
|_file||Access to open and read/write files.|
|_printer||Access to Windows print queues, so that output can be directly sent to the printer.|
When an object variable is on the left side of an assignment operator, the action depends on the object.
Object Type: _file
This object allows access to Windows files. Files can open created or existing files opened. Files can be read, write or appended.
|filename(??)||A Mandatory argument that specifies the filename to use. This name can either be an existing file or a new file.|
|flags(??)||Sets the mode which the file is opened. A list of comma separated keywords. The available keywords are: write, create, append. Write sets the file to be read/write mode. Create specifies that the file should be created new even if it already exists. Append specifies that the file should be opened for writing at the end, but if the file does not exist, if should be created also.|
set x = object(_file(filename(test.log) flags(append)))
set x = "Hello There"
set x = %013%
This examples writes the string Hello There, followed by a newline into the file test.log. Note the use of destroy x to close the file.
tax(Type , input-value)
The value of type can be taken from the following table:
|0||Calculate the tax contained within a price (ie in ) Example: 10c = tax(0, 0.90) in a 12.5% GST country|
|2||Calculate the tax applicable to a price (ie on ) Example: 10c = tax(2, 0.80) in a 12.5% GST country|
set x = 3
set answer = symbol(abc.%x%.def)
This script results in the variable answer being set to the value of the symbol abc.3.def
function(var , method)
|Money||round||Apply the current system rounding rules to this amount|
|Money||financialround||Round this amount to remove fractions of a cent (or whatever level of decimal points are normal for the currency being used).|
set x = float(0.6666666)
convert money x
set answer = function(x,financialround)
message(99,3,Money 0.6666666 financial rounds too %x%)
This script results in the variable answer being set to the value of the money value of 67 cents (in 2 decimal point countries).
right(var , length)
set x = "abcdef"
set answer = right(x,2)
This script results in the variable answer being set to the value "ef".
left(var , length)
set x = "abcdef"
set answer = left(x,2)
This script results in the variable answer being set to the value "ab".
left(var , position, length)
set x = "abcdef"
set answer = mid(x,2,2)
This script results in the variable answer being set to the value "cd".
When using the length operator, the variable name should not be enclosed in % subsitution characters, otherwise the length of the substituted result will be returned, not the variable itself.
set x = "abcdef"
set answer = length(x)
This script results in the variable answer being set to the value 6.
tablefield(table, field) provides quick check to see if the field exists on a table.
function(name) checks to see if specific POS functionality has been enabled.
file(filename) scans for the given name and returns true if it is present. The check is based on the current working directory.
set x = float(function(stickyprintformat))
This script results in the variable answer being set true or false depending on whether the current system has stickyprintformats configured.