Sample Four: Sample Notification Script

This sample is an example of a script that can be run from the notification context. The script changes a state value and writes a message to the Description field. The use case is that an existing item needs to be updated or transitioned by a user after a certain amount of time. If the user does not update the item in a timely manner, an escalation notification is triggered which fires the script and automatically moves the item to the "Escalated" state after the Time to Escalate has been exceeded.

There are three important considerations for creating a script for the notification context:

Note: To use this script, you must add it to SBM using the Scripts editor in SBM Composer. You must then associate it with a notification or escalation in Application Administrator.

This particular script requires a state named "Escalated", whose owner is the Manager User field with a database name of "MANAGER". It also assumes that the "DESCRIPTION" field is available and is a Journal field.

To test this script, perform the following in Application Administrator:

  1. Create two separate notification rules: "Any Item Is Submitted" and "State Changes."
  2. Create an escalation without a rule, whose Action is RUN SCRIPT. Select the sample script below (once it has been deployed from SBM) in the Script the Execute dropdown box. The escalation does not need any users selected on the Notify, Allow Subscriptions, or Subscribers tab.
  3. Create a notification with the "Any Item Is Submitted" rule. The notification does not need to perform an action, nor does it need any users selected on the Notify, Allow Subscriptions, or Subscribers tab. On the Escalation tab, select the "State Changes" rule in the Termination Rule dropdown box, then select Escalate Notification. Set the Time to Escalate to 3 minutes. In the Escalation to Send dropdown box, select the escalation you created in the previous step.
  4. Start the Notification Server if it was not started already.
  5. Submit a new item, but don't update or transition it before the Time to Escalate you designated in step 3 has lapsed. Refresh the item after the Time to Escalate and the item will appear in a new state.

Sample Notification Script Contents

' SBM AppScript Example: SampleNotificationScript.tsc

'
' Example script for the Notification context
'
' This script relies on a state called "Escalated", whose owner is the Manager user
' field with a database name of "MANAGER".
'
' It also assumes that the "DESCRIPTION" field is available and is a journal field.
'
Option Explicit
'Name of the escalated state
Const ESC_STATE_NAME = "Escalated"
Const FIELD_TO_MAKE_OWNER = "MANAGER"
Const JOURNAL_FIELD = "DESCRIPTION"
Dim id, tableId, item, escalatedStateId, flds, field, ownerValue
' Retrieve the item id and table id of the item - Shell.Item is not defined in this
' context
id = Shell.ItemId
tableId = Shell.TableId
' Create and read the record for this item
Set item = Ext.CreateAppRecord( tableId )
If ( item.Read( id ) ) Then
' At this point, item is essentially the same as Shell.Item in a transition context
' Get the state id for the "Escalated" state
escalatedStateId = GetStateIdByName( ESC_STATE_NAME, tableId )
If escalatedStateId <= 0 Then
Shell.RedoMessage = "Unable to find state with name " & ESC_STATE_NAME & _
" for escalating item " & id & " from table " & tableId & "."
Exit Sub
End If
' Update the value of the state field to the escalated state
If Not item.SetFieldValue( "STATE", escalatedStateId ) Then
Shell.RedoMessage = "Unable to set the value of the STATE field to " & _
escalatedStateId & " for escalating item " & id & " from table " & _
tableId & "."
Exit Sub
End If
' Append a journal note to the journal field stating why it was escalated
Set flds = item.Fields()
Set field = flds.FindField( JOURNAL_FIELD )
If field is Nothing Then
' Error finding the journal field - but let script complete
Call Ext.LogErrorMsg( "Unable to find " & JOURNAL_FIELD & " field when " & _
"escalating item " &  id & " from table " & tableId & "." )
End If
Call field.AppendJournalText( "Automatically escalated due to lack of timely " & _
"response." )
' Get the value of the field to make the owner- this needs to be set
' earlier in the workflow
If Not item.GetFieldValue( FIELD_TO_MAKE_OWNER, ownerValue) Then
' Error getting the value of the user field that will become the owner
Shell.RedoMessage = "Unable to obtain the value of the " & _
FIELD_TO_MAKE_OWNER & " field in order to " & _
"perform an escalation of item " & _
id & " from table " & tableId & "."
Exit Sub
End If
' Set the value of the owner field
If Not item.SetFieldValue( "OWNER", ownerValue ) Then
' Error setting the value of the owner field
Shell.RedoMessage = "Unable to set the value of the OWNER field to " & _
ownerValue & " in order to perform an escalation of item " & id & " from table " & _
tableId & "."
Exit Sub
End If
' Set some other fields that won't get set automatically from the notification
' context
Call item.SetFieldValue("LASTSTATECHANGEDATE",now)
Call item.SetFieldValue("LASTMODIFIEDDATE",now)
Call item.SetFieldValue("LASTSTATECHANGER",0)
Call item.SetFieldValue("LASTMODIFIER",0)
' Update the item in the database - stealing the lock if necessary
' Note that this has to be done explicitly in the notification context
If Not item.UpdateWithLock( true ) Then
' Error updating the item
Shell.RedoMessage = "Unable to update item " & id & " from table " & tableId & _
" in order to escalate the item."
End If
Else
Shell.RedoMessage = "Unable to read item " & id & " from table " & tableId & _
" in order to escalate the item."
End If
'
' Function to get the id of a state by the state name and table id
'
Function GetStateIdByName( strStateName, nTableId )
Dim nStateId, strFindState, objState
nStateId = 0
' Build the where clause
strFindState = "TS_NAME LIKE '" & strStateName & "' AND TS_PROJECTID IN " & _
"( SELECT TS_ID FROM TS_WORKFLOWS WHERE TS_TABLEID = " & _
nTableId & " )"
Set objState = Ext.CreateAppRecord( Ext.TableId( "TS_STATES" ))
If objState.ReadWithWhere( strFindState ) Then
nStateId = objState.GetId()
End If
GetStateIdByName = nStateId
End Function