Editing Event Actions |
Top Previous Next |
The Edit Event Action dialog is shown when adding or editing an Action from Event Actions Setup.
Action Name
The name should be descriptive enough for selecting the Action form the Setup list -- the name is not used anywhere else. Each Action must have a unique name (which is not case-sensitive).
Enabled
The Action can be disabled so that it does not get triggered regardless of the conditions. Technically you could also delete the Action, but if you might want to use it later or keep it for reference then it's better to just disable it. This is also handy for disabling Actions you haven't finished or tested sufficiently.
Note that Event Actions don't have an access level setting (presumably most actions should happen no matter who is logged in) -- if an action should depend on an access level, then include an expression to check the level of the current operator in the Condition (see below).
Event Trigger
Select the event from the list that you want to trigger your action. Note that most events have both a "before" and "after" option, so for instance you can do an action before and/or after the event is processed internally. As an example, you can have an action that does some validation before a reservation is checked in (optionally preventing the check-in with the Abort option below). You could also have an action that's triggered after the check-in is complete, such as printing a form (which would not get triggered if the check-in was aborted).
Note that there are some grey areas as far as exactly when the action will be triggered, which means the internal sequence is not strictly defined and could change in future versions. For instance an after-check-in action is guaranteed to be triggered after the "Checked In" status is changed for a reservation, but it whether it's triggered before or after the charges and payments are applied, a receipt is printed, and other synchronized reservations are updated is all grey area -- so try not to assume anything about related changes.
While there are events for viewing customer and reservation details and transactions, don't forget that the Dialog customizations can also allow expressions to be executed when entering or exiting these dialogs (after the dialog is opened and before it's closed, as opposed to before it's opened and after it's closed). The exact nature of what you need to do might make using one or the other of these customizations more appropriate.
Time Triggers
There are triggers for "Every Second", "Every Minute", "Every Hour" and "Every Day". They sound self-explanatory enough, but there are several caveats to these.
Generally these are triggered at the "change" of the minute, hour, and day (when the system first notices that it has changed, e.g. the "Every Hour" trigger will happen as soon as the hour digit changes on the clock).
However, timed events are suspended when any dialog is open so that the operator is not interrupted (and because the data could be in an inconsistent state while a dialog is open). Once all dialogs are closed, then event checking is resumed. For "Every Second" events, this generally means that all intervening triggers are lost (e.g. it won't try to catch up with possibly 100's of "missed" triggers). However it does check against the last time an event was actually triggered, so for instance if the Minute or Hour rolled over while a dialog was open, then that event will immediately be triggered as the change is noticed. Of course this also means that the event is not guaranteed to happen "exactly" at the roll-over time.
It can be difficult to get events to happen at regular intervals with any consistency. For instance if you want something done every 30 minutes, one method would be to define an "Every Minute" trigger, and use the Condition expression to check for the current time's Minutes being either 0 or 30. However, if a dialog is open for more than a minute, e.g. from 3:59 to 4:01, then the event completely misses the 4:00 check and the condition won't be met until 4:30 (assuming a dialog is not open then also...). One way around this is to create your own Setting that stores the last time your Condition expression was executed, and check for that being 30 minutes ago (or longer). Then you don't rely on the exact time the event is triggered, but it's still subject to how long a dialog is left open, so intervals would commonly vary from 30 minutes to perhaps 45 minutes or more, depending on how long an operator works on something.
Important Note: It may be tempting to do something like this Every Second to make sure it's checked as often as possible. However you don't want to execute a complex expression every second, since it could significantly lock up the system, so be conservative on how often something needs to be done. For instance, setting the value of a Setting can take significant time because it involves a database change (which means immediately saving the database to the hard disk, refreshing views, synchronizing other workstations, etc.), which could completely lock up the system. (In fact it would be more efficient to use a file to read & write the last-checked time, since it won't affect anything else and is much faster than writing the whole database.)
Condition
This expression is executed when the action is triggered, and the result determines whether the Action is executed. Naturally the result should be a boolean (True or False) value, or else leave the expression blank to always execute the Action.
To edit the condition expression, click on the text box or click the Edit button next to it. The Expression Creator dialog will be used to enter the expression.
Action
This is the expression to execute for the event (if the Condition is met, of course). If the event involves a particular record, e.g. a Reservation being checked in, then the appropriate context information will be available to the expression. The result of the expression is ignored and can be any type of value unless the Abort option is selected (below).
To edit the action expression, click on the text box or click the Edit button next to it. The Expression Creator dialog will be used to enter the expression.
Context
If the event involves a particular record, e.g. an event for a particular Reservation, then the appropriate context information will be available to the expression from the ThisRecord() function. If the event also involves a specific date, for instance the events for right-click functions on the Rack like Extend Reservation, then ThisFromDate() and ThisFromPeriod() context will also be available. There are also some special cases -- for instance in the Monthly billing, Meter reading, Select Rates and Auto-Rates "before" events, ThisListCount() and ThisListRec() can be used to get the transactions about to be added (allowing you to change the transaction details before they're added).
However there are also some exceptions to the general rules. For instance, the Edit Customer event may be triggered from Add Customer, in which case ThisCust() will not be valid -- it would only be valid if the event is triggered when a customer is already known, such as from a right-click "Customer Details" action. Also, for the Split Reservation event and possibly some other events triggered from right-click menus, the normally intuitive ThisDate() is not set -- instead, use ThisFromDate() (this is because some cases may involve both a From date and a To date).
Abort the Event....
If this option is selected, then the result of the Action expression is checked for a False (.F.) value (the result of the Action expression should be a boolean value, of course). If it's False, then any further processing for the event which triggered this action will be aborted. Obviously this is usually only useful for a "before" type of event trigger, since the "after" triggers only happen after all of the important stuff has already happened. However if you define more than one "after" action for the same event, then aborting will stop any following Actions from being processed.
This is generally used to check some special condition before continuing with an event like checking in, checking out, etc. You could even open a special dialog or prompt for the user (e.g. "Is the customer over 18 years old?"), and decide whether or not to continue based on the results.
Note: It's usually a good idea to include a MessageBox( ) function in the Action expression to show a message if you're going to abort further processing, so that the user knows that the event is going to be aborted (and why).
Additional Topics:
Advanced Customizations Overview & other topics