{{tag>Manuals Rule_Language}}
====== Rule Language Cheat Sheet ======
One page with the whole AwareIM rule language: the rule shape, the conditions, the most used actions and functions, about 20 ready patterns and the mistakes people make most. Every item links to its full page.
===== Rule shape =====
IF (RuleCondition) THEN
ActionList
ELSE IF (RuleCondition) THEN
ActionList
ELSE
ActionList
''IF'' and ''ELSE'' are optional. A rule with only actions is an //unconditional rule//. See [[3000_rule_language:0300_rule_language|Rule Definition]].
===== Names and values =====
^ Write ^ Meaning ^
| ''Account.State'' | attribute of an object |
| ''Account.Type.Name'' | attribute of a referred object (any depth) |
| ''3'', ''5.6'' | number |
| ''%%'%%CLOSED%%'%%'' | string (apostrophes, not quotes) |
| ''`CLOSED`'' | string with backticks (the key under ~): use it when the text holds apostrophes |
| ''05/12/98'' | date (''dd/mm/yy'') |
| ''05/12/98 17:05'' | date/time (''dd/mm/yy HH:mm'') |
| ''2w3d10:45'' | duration (weeks, days, hours:minutes) |
| ''UNDEFINED'' | empty value |
See [[3000_rule_language:0400_rule_language#literal|Literal]].
===== Conditions =====
Join conditions with ''AND'' / ''OR''. Put ''NOT ( … )'' around a condition to negate it.
^ Pattern ^ Example ^
| compare: ''=, <, >, %%<=%%, %%>=%%, <>'' | ''Account.Balance < Account.Type.MinBalance + 100'' |
| text | ''Account.Name STARTSWITH 'John%%'%%'' (also ''ENDSWITH'', ''CONTAINS'') |
| one of these values | ''Account.State IN 'Open', 'Closed%%'%%'' |
| range (both ends included) | ''Account.Balance BETWEEN 10000 AND 20000'' |
| empty / filled | ''Account.State IS UNDEFINED'' / ''Account.State IS DEFINED'' |
| object is being created | ''Message IS NEW'' |
| value changed | ''Account.State WAS CHANGED'', ''Account.State WAS CHANGED TO 'Open%%'%%'' |
| list changed | ''Transaction WAS ADDED TO Account.Transactions'', ''Transaction WAS REMOVED FROM Account.Transactions'', ''Transaction FROM Account.Transactions WAS CHANGED'' |
| any object exists | ''EXISTS Account WHERE (Account.State = 'Open')'' |
| object is in a reference list | ''Transaction IN Account.Transactions'' |
| user is logged in | ''SystemUser IN LOGGED_IN_USERS'' |
| negate | ''NOT (Account.State IN 'OPEN', 'CLOSED', 'SUSPENDED')'' |
See [[3000_rule_language:0400_rule_language|Rule Condition]].
===== Totals =====
''SUM'', ''COUNT'', ''MIN'', ''MAX'', ''AVG'', with an optional ''WHERE (…)'':
SUM Account.Balance WHERE (Account.State='OPEN')
COUNT Account WHERE (Account.State='Open')
See [[3000_rule_language:0400_rule_language#aggregate_operation|Aggregate Operation]].
===== Calculations =====
^ Write ^ Result ^
| ''%%'%%John' + ' ' + 'Smith%%'%%'' | ''John Smith'' (strings join with ''+'') |
| ''%%'%%Number' + Account.Balance'' | a string, e.g. ''Number1000'' |
| ''Account.OpeningDate + 7'' | the date 7 days later |
| ''Transaction.Timestamp - 3'' | the timestamp 3 hours earlier |
| ''Account.Balance - Transaction.Amount'' | an ''UNDEFINED'' value is left out (result = ''Account.Balance'') |
See [[3000_rule_language:0700_rule_language|Notes on rule execution]].
===== Instance prefixes =====
Use these when the Context holds more than one instance of the same object.
^ Prefix ^ Means ^
| ''This'' | the first instance in the Context (e.g. the object the rule belongs to) |
| ''That'' | the second instance (usually found by ''FIND'' or made by ''CREATE'') |
| ''Other'' | all instances after the first |
| ''LoggedIn'' | the user who is logged in, e.g. ''LoggedInAssociate'' |
| ''Added'', ''Removed'', ''Changed'' | the list item that was added, removed or changed |
| ''Failed'' | the object that made a process fail |
See [[2000_concepts:0800_data_processing:0100_rule_evaluation:0800_context_rule_execution:0200_instance_prefixes|Instance Prefixes]].
===== Most used actions =====
^ Action ^ Example ^
| [[ref:a_f:a:assignment|assign]] | ''Account.State = 'Open%%'%%'', ''Member.Loans = UNDEFINED'' |
| [[ref:a_f:a:increment|INCREASE / REDUCE]] | ''INCREASE Account.Balance BY 1000'', ''REDUCE Account.Balance BY 5%'' |
| [[ref:a_f:a:create|CREATE]] | ''CREATE Account WITH Account.State='Open', Account.Balance=0'' |
| [[ref:a_f:a:find|FIND]] | ''FIND Account WHERE Account.State = 'Open%%'%%'', ''FIND ALL Account'', ''FIND 'Open accounts%%'%%'' (a query) |
| [[ref:a_f:a:delete|DELETE]] | ''DELETE Account'' |
| [[ref:a_f:a:insert|INSERT]] / [[ref:a_f:a:remove|REMOVE]] | ''INSERT Transaction IN Account.Transactions'', ''REMOVE Transaction FROM Account.Transactions'' |
| [[ref:a_f:a:report_error|REPORT ERROR]] | ''REPORT ERROR 'Account with non-zero balance cannot be closed%%'%%'' |
| [[ref:a_f:a:protect|PROTECT]] | ''PROTECT Transaction FROM ALL EXCEPT Administrator'' |
| [[ref:a_f:a:send|SEND]] | ''SEND ReservationOfferNotification TO Reservation.Member VIA Email'' |
| [[ref:a_f:a:display_message|DISPLAY MESSAGE]] | ''DISPLAY MESSAGE 'Items have been created%%'%%'' |
| [[ref:a_f:a:display_question|DISPLAY QUESTION]] | ''DISPLAY QUESTION 'Do you want to print out a receipt?%%'%%'' |
| [[ref:a_f:a:view|VIEW]] | ''VIEW Account USING 'Some fancy form%%'%%'' |
| [[ref:a_f:a:start_process|START PROCESS]] | ''START PROCESS Object.Attribute'' |
| [[ref:a_f:a:exec_sql|EXEC_SQL]] | ''EXEC_SQL `SELECT CRM_Customer WHERE FirstName='Jane'` RETURN Customer'' |
All actions: [[3100_actions_functions:3100_actions|Actions]].
===== Most used functions =====
^ Function ^ Example ^
| [[ref:a_f:f:af:current_date|CURRENT_DATE]] | ''Account.OpeningDate=CURRENT_DATE'' |
| [[ref:a_f:f:af:current_timestamp|CURRENT_TIMESTAMP]] | ''Transaction.Time = CURRENT_TIMESTAMP'' |
| [[ref:a_f:f:af:date_add|DATE_ADD]] (days) | ''DATE_ADD (Account.OpeningDate, 4)'' |
| [[ref:a_f:f:af:month_add|MONTH_ADD]] | ''MONTH_ADD (Account.OpeningDate, 4)'' |
| [[ref:a_f:f:af:day_difference|DAY_DIFFERENCE]] | ''DAY_DIFFERENCE (Account.OpeningDate, Account.ClosingDate)'' |
| [[ref:a_f:f:af:year_difference|YEAR_DIFFERENCE]] | ''YEAR_DIFFERENCE (Account.OpeningDate, Account.ClosingDate)'' |
| [[ref:a_f:f:af:age|AGE]] | ''AGE (Account.Customer.DateOfBirth) > 70'' |
| [[ref:a_f:f:af:length|LENGTH]] | ''LENGTH (Account.Name)'' |
| [[ref:a_f:f:af:substring|SUBSTRING]] | ''SUBSTRING (Account.Name, 0, 4)'' (second index not included) |
| [[ref:a_f:f:af:index_of|INDEX_OF]] | ''INDEX_OF ('Smith', Account.Name)'' (0 = not found) |
| [[ref:a_f:f:af:to_upper_case|TO_UPPER_CASE]] | ''TO_UPPER_CASE (Account.Name)'' |
| [[ref:a_f:f:af:trim|TRIM]] | ''TRIM (Account.Name)'' |
| [[ref:a_f:f:af:as_string|AS_STRING]] / [[ref:a_f:f:af:as_number|AS_NUMBER]] | ''AS_STRING (Account.Number)'', ''AS_NUMBER (Account.Text)'' |
| [[ref:a_f:f:af:round|ROUND]] | ''ROUND (6.738, 2)'' = ''6.74'' |
| [[ref:a_f:f:af:list_size|LIST_SIZE]] | ''LIST_SIZE (Client.Children) > 2'' |
| [[ref:a_f:f:af:old_value|OLD_VALUE]] | ''OLD_VALUE (Account.Balance)'' |
All functions: [[ref:a_f:f:af|All Functions]].
===== Patterns =====
==== Stop a save with an error ====
IF Account.State='CLOSED' AND Account.Balance<>0 THEN
REPORT ERROR 'Account with non-zero balance cannot be closed'
==== Allow only one record with a name ====
IF EXISTS SystemUser WHERE (SystemUser.LoginName = ThisSystemUser.LoginName) THEN
REPORT ERROR 'User with this name already exists'
==== Fill an empty reference ====
IF Account.Type IS UNDEFINED THEN
FIND AccountType WHERE AccountType.Name='Credit' Account.Type=AccountType
==== Calculate a value ====
CreditAccount.AvailableFunds = CreditAccount.CreditLimit+CreditAccount.Balance-CreditAccount.NonClearedFunds
==== Keep a total in step with a list ====
IF Transaction WAS ADDED TO Account.Transactions THEN
INCREASE Account.Balance BY AddedTransaction.Amount
IF Transaction WAS REMOVED FROM Account.Transactions THEN
REDUCE Account.Balance BY RemovedTransaction.Amount
IF Transaction FROM Account.Transactions WAS CHANGED THEN
INCREASE Account.Balance BY (ChangedTransaction.Amount - OLD_VALUE(Transaction.Amount))
==== Lock a field after the record is created ====
IF NOT (Message IS NEW) THEN PROTECT Message.Subject
==== Lock a record by its state ====
IF Transaction.State='APPLIED' THEN
PROTECT Transaction FROM ALL EXCEPT Administrator
Users cannot change the field, but processes can:
IF Account.STATE <> 'NEW' THEN
PROTECT Account.Balance FROM ALL EXCEPT System
Hide records completely (not read from the system):
IF Transaction.State='APPLIED' THEN
READ PROTECT Transaction FROM ALL
==== Do something when a state changes ====
IF Account.State WAS CHANGED TO 'Open' THEN ...
==== Create a related record ====
CREATE Account WITH Account.State='Open', Account.Balance=0
One record per day of a period:
CREATE Transaction FOR EACH DAY BETWEEN Account.OpeningDate AND Account.ClosingDate WITH Transaction.AppliedDate=LOOP_ITERATION
==== Find the top 5 ====
FIND ALL Account ORDER BY Account.Balance DESC TAKE BEST 5
==== Work through many records in batches ====
FIND Account WHERE Account.State = 'OPEN' AND Account.Balance > 1000 ORDER BY Account.Balance IN BATCHES OF 5
==== Ask the user, then act on the reply ====
DISPLAY QUESTION 'Do you want to print out a receipt?' YESNAME 'I do' NONAME 'I do not'
IF Question.Reply = 'Yes' THEN ...
==== Show a short message in a corner ====
DISPLAY MESSAGE ASYNCH BOTTOM_LEFT 'Items have been created'
==== Send an email ====
SEND ReservationOfferNotification TO Reservation.Member VIA Email
From a specific email account (an EmailAccount object in the Context):
SEND ReservationOfferNotification TO Reservation.Member USING EmailAccount
==== Act for the logged-in user ====
IF LoggedInAssociate.LoginName='john' THEN DoSomething
===== Common mistakes =====
**Totals cannot go through a reference.**
Wrong: ''SUM Account.Transactions.Amount''
Right: ''SUM Transaction.Amount WHERE (Transaction IN Account.Transactions)''
**COUNT takes an object name only.**
Wrong: ''COUNT Account.Transactions''
Right: ''COUNT Transaction WHERE (Transaction IN Account.Transactions)''
**No date or timestamp arithmetic inside FIND.** Calculate the date first, then use it in the ''FIND''.
**PROTECT only works in rules attached to the object it protects** Never in a process, and never on an attribute of a referred object (''PROTECT Transaction.Account.State FROM ALL'' is invalid).
**A string inside a string: use the other mark.** A string can be wrapped in apostrophes (') or backticks (`). Inside it, use the one that is not on the outside.\\
Right: ''REPORT ERROR 'John`s error!%%'%%''\\
Right: ''REPORT ERROR `My error message is 'Blah-blah'`''\\
Right: ''DISPLAY URL 'logonOp.aw?e=ENCRYPT_B64(`domain=Test`)%%'%%''\\
Right, SQL (backticks outside, so the SQL gets real apostrophes): ''EXEC_SQL `UPDATE CRM_Customer SET Name='John'`''\\
Right, HTML or JavaScript in a string (backticks outside, so the script gets real apostrophes): ''MyObject.myattribute=``''\\
Wrong: ''REPORT ERROR 'My error message is 'Blah-blah'%%'%%''
* Strings use apostrophes: ''%%'%%Open%%'%%''. A query name with spaces also needs them: ''FIND 'Open accounts%%'%%''.
* Strings only support ''+''. Yes/No and Document attributes cannot be used in calculations.
* ''<, >, %%<=%%,%%>=%%'' only work on numbers, dates and durations.
* In comparisons an ''UNDEFINED'' value counts as 0.
* ''BETWEEN'' includes both ends.
* A condition on a reference list (''Customer.Policies.CarType='Wagon%%'%%'') is true when //any// item in the list matches.