The TACTIC Event System is built into the base transactional system in Tactic's core. Every transaction which occurs in Tactic can fire an event which in turn, can be used to execute a trigger or notification.
These events can be incorporated to automate specific processes that are often repetitive. At the simplest level, there are interfaces that help prepare and configure these aspects but, it is good to understand how they work. Overall, there are 2 levels that these events can be configured. The first is using the predefined event options provided in the Project Workflow or Project Schema interfaces and the second in the low level database events.
The following list of events are the events provided in the Project Workflow interface. For more information in setting up Notifications and Triggers with this interface, please refer to Project Automation - Triggers and Project Automation - Notifications
A task Status is Changed | When the status of a task is changed. Further options are provided allowing for selection. |
A new note is added | When a new note (sthpw/note) is added to the project. |
A task is assigned | When a task is assigned to a user. |
Files are checked in | When files are checked in to an SObject. |
Files are checked out | When files are checked out from an SObject. |
Custom event | Allows for calling of an event using the raw Database Events. |
Below is the list of the database level events. These events are run regardless of how they are called (interface, api, external integration etc)
done | Executed each time a transaction completes |
insert | Executed each time a Search Object has been inserted. |
update | Executed each time a Search Object has been updated. |
change | Executed each time a Search Object has changed. This combines the events insert, update and delete. |
retire | Executed each time a Search Object has been retired. |
delete | Executed each time a Search Object has been deleted. |
checkin | Executed each time a checkin occurs for a Search Object |
checkout | Executed each time a checkout occurs for a Search Object |
timed | Executed on a timed interval. This is only supported for triggers. |
For example, in a transaction where the status of a task is being changed, an association to this event can be made with the following notation:
update|sthpw/task|assigned
The notation can consist of 3 sections although only the event is required.
<Event>|<SType>|<Column>
Event | The raw database event. |
SType | The Searchable Type (SType) the event is occurring for. |
Column | The Column that was changed in the SType. |
Triggers are events that are called upon a transaction to automate workflow. These triggers can be accessed within the Project Workflow view.
Admin Viwes -> Project Admin -> Project Workflow
Each process in the pipeline can have their own triggers. Right clicking on a process and choosing show notification/trigger option will open a tab to define a trigger for that specific process.
The trigger tab will also display the assigned process. Clicking the insert button will open the trigger UI.
Title | Title of the trigger. |
Description | Description of the trigger. |
Unique Code | |
Event | Drop down list of trigger events. This event is where the trigger is called. |
Action | The action is what the event will |
The Events drop down list provides a wide range of different triggers.
Depending on the trigger the Event box may show additional options.
A new note is added - This Event will be called when a new note is inserted into the process.
A task status is changed - This event will be called when a status is changed. The event box also gives a additional option to choose specific status.
A task is assigned - This event will be called when any task in the specified process is assigned.
Files are checked in - This event will be called when there is a checkin to the specified trigger. This event also gives a additional option to choose what process the action will effect.
Files are checked out - This event will be called when there is a checkout to the specified trigger.
Cusom Event -
The Action drop down list provides a series of predifined actions that work with the above events.
Send a notification - See project automation notification docs.
Update another task status - This action will update a task status. This action also opens additional options to update status of current and other process of the pipeline as well as the option of status.
Create another task - This Action will create a task upon event. This action also opens additional options to choose from creating a task in current or next process.
Run python code - This Action will run python code upon event. The action box opens additional options to name and insert a python code.
Run python trigger - This Action will run python trigger upon event. The action box opens additional option to insert the name of the trigger. These can be custom written scripts that can be called from Tactic's API.
When satisfied with the options set to run a trigger, the trigger must be saved in order to be applied. When the trigger is saved the title of the trigger will appear benieth the triggers panel.
There are no limitations of how many triggers you can have. Each process can have multiple triggers applied.
Notifications are sent to inform the user that a particular transaction or event has occurred.
They are stored in a notification_log which can be found under Admin Views -> Site Admin -> Notifications.
Notifications present information reported by transactions. They usually include what items are created or updated in addition to a description of the command. Below is an example of a notification:
With the mail server setting set up properly (set in the TACTIC Config file), TACTIC can send out email notifications to users.
There are 2 perspectives to work from when configuring notifications in TACTIC.
Project Workflow - Notifications can be set up per process in a pipeline which are used to automate the pipeline/workflow
Project Schema - Notifications can be set up at a simpler level where any of the Raw Database events can be used to trigger a notification regardless of process.
In the Workflow Editor, right click on a process and choose show notification/trigger to open a tab to define a trigger for that particular process.
This will open a new Triggers tab in the panel at the bottom for the assigned process.
Click the [+] button to insert a trigger. This will open the trigger/notification UI.
Notifications and Triggers work together in many ways. A notification is defined as an Action. To send a notification, an event must occur.
In the Action drop down list Send a Notification must be selected.
Send a Notification - This action will send a notification. The action box will open additional options to insert a subject and message.
Below is an example of a notification being sent on the event when a task status is changed to review:
The Mail To: and Mail CC: input fields accepts the following types of input:
Email - Capability to add regular emails allows to send personal email addresses e.g. joe@my_email.com
Group - Capabilty to send to a group of users in TACTIC e.g. Supervisor
Expression - Capabilty to insert expressions that specifies a user in TACTIC. All expressions are identified by curly brackets "{}". e.g. {@SOBJECT(sthpw/login)}
Send a Notification - This action will send a notification. The action box will open additional options to insert a subject and message.
Below is an example which uses more expressions for a notification being sent whenever a task is assigned.
The notification view is located in the TACTIC Sidebar under:
Site Admin -> Notifications
This can also be accessed through the Workflow Editor, by right clicking on a node and selecting from the context menu Show Triggers/Notifications.
This view provides all the functionality required to set up the various types of notifications used to establish better production communication and instant status updates.
To insert a new notification, select from the sidebar:
Site Admin -> Notifications
The following table explains the basic usage of each property.
Event | The TACTIC event to execute the notification for |
Process | Events relating to note, task, snapshot can make use of process to differentiate |
Description | The description of the purpose of the notification |
Subject | The subject of the notification. This uses the TACTIC Expression Language |
Message | The message body for the notification. This uses the TACTIC Expression Language |
Rules | The XML access rules used to filter the notification further |
Email Handler Class | The email handler class override for the notification. This allows for overriding of the notification with a python email handler class. This only needs to be used in specific situations. |
Project Code | The project code for the notification. This allows for filtering of notifications for a specific project |
Type | The type of notification being sent. By default for notifications, this must be set to "email" |
Mail_to | An expression of the users to mail to in the email (supports multiple lines of expressions and / or email addresses and names of groups of users made in TACTIC) |
Mail_cc | An expression of the users to mail to in the email. It will appear in the cc category. (supports multiple lines of expressions and / or email addresses and groups) |
Mail_bcc | An expression of the users to mail to in the email. It will appear in the bcc category. (supports multiple lines of expressions and / or email addresses and groups) |
Below are examples of what can be used in mail_to, mail_cc, or mail_bcc:
For example, email the user 'admin' only:
@SOBJECT(sthpw/login['login', 'admin'])
For example, send to the user related to this sObject. If this is an event for task update, the email will be addressed to the assigned user:
@SOBJECT(sobject.sthpw/login)
For example, send to the user related to this sObject as well as the user 'john'. If the event is insert|sthpw/note, it will be the person who enters the note. If the event is 'update|sthpw/task', the person is the assignee of the task:
@UNION(@SOBJECT(sthpw/login['login', 'john']), @SOBJECT(sobject.sthpw/login))
To make these mail_to expressions more readable, put more than 1 expression or email addresses on multiple lines. There is no need for @UNION. @GET can even be used to just get to the list of login names.
For example, to send to everyone in the supervisor group, the assignee of a task, to all the users in the mangers group and the email address support@southpawtech.com, enter 3 lines under mail_to:
@SOBJECT(sobject.sthpw/login) @GET(sthpw/login_in_group['login_group','supervisor'].login) managers support@southpawtech.com
More on Expressions in Notifications
The word "sobject" often appears in the Mail to: column but not in Message or Subject. This is because the implementation allows sending notifications to users related to the current sObject or just about anyone not necessarily related to the current sObject. As illustrated above, @SOBJECT(sobject.sthpw/login) is the task assignee but the users under the group supervisor is not related to this task and so the keyword "sobject" is not used. In the Message area, to refer to the current sObject status (task status if the event is update|sthpw/task), just use an @GET(.status), as the sobject is always assumed to be in this context.
Task related notification
To establish the relationship between the login search type and task search type, the following built-in schema line is used. It is not necessary to add it to the schema. It can be used as an example to create a custom search_type.
<connect to='sthpw/task' relationship='code' from_col='login' from='sthpw/login' to_col='assigned'/>
Note related notification
To establish the relationship between the login search type and note search type, the following built-in schema line is used. It is not necessary to add it to the schema. It can be used as an example to create a custom search_type and to edit the schema.
<connect to='sthpw/note' relationship='code' from_col='login' from='sthpw/login' to_col='login'/>
Sending a notification to the person who just entered the note is not often used. Instead, an email handler can be used in this situation to send to the supervisor and assignee of the task under the same context. A built-in email handler is called "pyasm.command.NoteEmailHandler". Instead of entering it into an expression for mail_to, enter it into the email_handler_class field.
Once the fields event, mail_to, and message are properly filled in, to test the email, click on the Email Test button. It catches syntax errors or typos in expression in these fields as well as reporting any email server error if the service section of the TACTIC config file has not been properly filled in. Settings like firewall and TLS settings may also block an email from being sent out.
In this example, the notification will be sent out each time a ticket is updated. It will also only send to users in the 'admin' and 'moderator' groups.
Event | update|support/ticket |
Description | Sent when tickets are updated |
Subject |
TACTIC Ticket {@GET(.id)} Has been updated. |
Message |
{@GET(.company_code)} TACTIC Ticket {@GET(.id)} has been updated. Subject: {@GET(.subject)} Summary: {@GET(.summary)} Status: {@GET(.status)} From status: {@GET(sthpw/status_log['@LIMIT','1'].from_status)} Please do not reply to this e-mail. To reply or to make further comments, please login to the Ticketing system @ http://tickets.southpawtech.com/tactic |
mail_to |
admin moderators |
Rules | |
Email Handler Class | |
Project Code | support |
Type |
In this example, the notification will be sent out each time a shot-based note is updated. It will send to manager's group and everyone assigned to the tasks of the shot. Since project_code is left empty, this works across all the projects in the system.
Event | insert|sthpw/note |
Description | Sent when shot-based notes are added |
Subject |
{$PROJECT} {@GET(parent.sequence_code)} - {@GET(parent.code)} {@GET(.process)} |
Message |
Project: {$PROJECT} Code: {@GET(parent.sequence_code)}, {@GET(parent.code)} Process: {@GET(.process)} Note: {@GET(.note)} To reply or make further comments: please go to http://<some IP>/tactic/{$PROJECT}/#/link/my_notes |
Rules | <rules> <rule>'prod/shot' in @GET(.search_type)</rule> </rules> |
Email Handler Class | |
Project Code | |
Type | |
mail_to | @GET(sobject.parent.sthpw/task.assigned) @GET(sthpw/login_in_group['login_group','manager'].login) |
The following sections explain each configuration aspect of Notifications in greater detail
TACTIC uses the TACTIC Expression Language to build dynamic Notification Subject and Message contents. This allows for each notification to be sent based on properties from the Search Objects it is being sent for.
In the simple example Subject below, the "id" property is used from the "ticket" search object.
TACTIC Ticket {$GET(.id)} has been updated
The expected results of this would be similar to the following:
"TACTIC Ticket 14 has been updated"
In essence, anything between the curly brackets "{}" is evaluated as an expression by TACTIC.
For more information regarding TACTIC Expression Language please refer to the TACTIC Expression Language docs
TACTIC's notification architecture is a rules-based system built using the trigger architecture. Every time a command is executed, TACTIC looks through the list of defined triggers (including notifications) for a match. Under the Triggers view will be an entry for the EmailTrigger class that is registered under the "email" event. It is possible to create custom Email Trigger handlers in that view.
There are 3 main criteria used to filter out notifications:
group: Filters out notifications to be sent only to users in the included groups.
project: Filters out notifications so that only a certain project can fire the email trigger.
rules: Rules are an XML snippet which can finely control the conditions when an email trigger may be fired.
By planning groups to send notifications to, it allows for simple connections for deciphering which groups of users will receive notifications when the conditions of a particular notification rule are met. Once a notification has been created, it can be associated with any number of groups of users. All users in this group will then be sent a notification when the rule is triggered.
The Groups view can be found under:
Admin->Site Admin ->Groups
To specify a group to send a notification to, specify the group in the mail_to column.
By setting the project in the project column of a Notification, TACTIC will only use the notification trigger for the chosen project.
When a notification rule has passed all of the criteria, a message is constructed. Most email events occur after a command has been completed. The email handler then takes the information from the command and creates a default message to be sent to the appropriate people.
All rules are contained in groups. For notifications, there are a few predefined groups:
This rule group only allows tasks for prod/asset for the project sample3d to send out notification. Otherwise, it would send out notifications for tasks of all search types
<rules> <rule>@GET(.search_type)=='prod/asset?project=sample3d'</rule> </rules>
This rule group makes use of a key/value pair of attributes: that is, when the attribute with the value of "key" is equal to "value", the rule is passed. In the example below, all SObjects containing the attribute "context" with the value "client" are triggered.
(deprecated) <rules> <rule group="SObject" key="context" value="client"/> </rules>
<rules> <rule>@GET(.context)=='client'</rule> </rules>
For certain SObjects in TACTIC (like tasks), parent attributes can be used for constructing rules. The concept behind this is the same as group="sObject", but now we are referring to the parent of a task (for example, a 3D asset). This notification will only be sent if the task's parent, a 3D asset, is categorized under the "prp" asset library.
<!-- DEPRICATED --> <rules> <rule group='parent' key='asset_library' value='prp'/> </rules>
<rules> <rule>@GET(prod/asset.asset_library)=='prp'<rule> </rules>
For notes in TACTIC, we may have 2 processes for notes (e.g. anim, anim_2) We can check if the process partially contains the word anim by the following:
<rules> <rule>'anim' in @GET(.process)<rule> </rules>
Note: list comparisons like @GET(.process) in ['anim','anim_2'] are not supported
For a check-in notification in TACTIC, we can choose to send only if the is_current attribute is True for the event insert|sthpw/snapshot by the following:
<rules> <rule>@GET(.is_current)==True<rule> </rules>
Each time a notification is executed, TACITC uses either the default email handler or it uses and email handler override defined by the Email Handler Class property for the notification.
The Email Handler Class digs deeply into the structure of the notifications using Python and the TACTIC client API. It is only needed for very specific rules which determine when a notification is sent.
An example override is shown below:
Email Hander Cls: sites.support.email.TicketEmailHandler
__all__ = ['TicketEmailHandler'] from pyasm.common import Environment, Xml, Date from pyasm.security import Login from pyasm.search import Search from pyasm.biz import GroupNotification, Pipeline, Task, Snapshot, File, Note class TicketEmailHandler(object): '''Email sent when a ticket is updated''' def __init__(my, notification, SObject, parent, command): my.notification = notification my.sobject = SObject my.command = command my.parent = parent def check_rule(my): '''determine whether an email should be sent''' return True def get_to(my): ticket = my.sobject user = ticket.get_value("login") login = Login.get_by_login(user) recipients = [] recipients.append(login) return recipients def get_cc(my): admin = Login.get_by_login("admin") recipients = [] recipients.append(admin) return recipients def get_subject(my): ticket = my.sobject title = "Ticket Number: " id = ticket.get_value("id") return "%s%s" % (title, id) def get_message(my): ticket = my.sobject id = ticket.get_value("id") subject = ticket.get_value("subject") summary = ticket.get_value("summary") status = ticket.get_value("status") msg = [] msg.append("Ticket: %s" % id) msg.append("") msg.append("Status: %s" % status) msg.append("") msg.append("subject: %s" % subject) msg.append("Summary: %s" % summary) msg.append("") return "\n".join(msg)