The following scripts provide examples of using custom Python scripting capabilities in a typical
Agiloft installation. The
Agiloft distribution includes Python and will automatically use it to execute scripts with a .py extension. If you want to use your own version of python, you may do so by setting the KB global variable "Location of external Python directory".
You must call these functions in every Python script used in
Agiloft in order for the script to terminate properly:
set_data.exitAction(ALset.ACCEPT)
set_data.save()
Samples
Click a sample below to see the script text.
######################################################################
# Synopsis:
#
# Redirect the user after he/she submits the ticket.
#
# There is no need to specify the Python interpreter if the script is named *.py
# because the system recognizes .py scripts as being Python based and will
# use the Python that is included in the distribution.
#
# If you use this script with your own copy of Python, please note that
# it requires ElementTree module to be installed
#
######################################################################
import sys
from ALget import ALget
from ALset import ALset
def action(inputXMLFile, outputXMLFile):
get_data = ALget(inputXMLFile)
set_data = ALset(outputXMLFile)
######################################################################
#
# Only log the user out if he/she is not a member of the Staff
# group. In other words, we want all members of staff to be able
# to log tickets on behalf of users without being logged out.
######################################################################
groups = get_data.globalVariable('my_groups')
groupAllowedToClose = "Staff"
if groupAllowedToClose not in groups.split(","):
set_data.redirect("http://www.example.com")
set_data.exitAction(ALset.ACCEPT_REDIRECT)
else:
set_data.exitAction(ALset.ACCEPT)
set_data.save()
action(sys.argv[1], sys.argv[2])
#####################################################################
# Synopsis:
# Send new users a confirmation email with their login and password
#
# There is no need to specify the Python interpreter if the script is named *.py
# because the system recognizes .py scripts as being Python based and will
# use the Python that is included in the distribution.
#
# If you use this script with your own copy of Python, please note that
# it requires ElementTree module to be installed
#
######################################################################
import sys
from ALget import ALget
from ALset import ALset
import smtplib
from email.mime.text import MIMEText
######################################################################
# Only send email to members of the Customer group.
# For security reasons, it is unsafe to send password information in
# plain text to privileged groups such as staff or admin.
######################################################################
def action(inputXMLFile, outputXMLFile):
get_data = ALget(inputXMLFile)
set_data = ALset(outputXMLFile)
groups = get_data.valueMultipleLF("f_group")
me = "support@CompanyName.com"
you = get_data.value("email")
if groups and groups.containsValue("Customer") and you:
body = ("Dear " + get_data.value("full_name") + ",\n"
"Thank you for registering with our support system.\n\n"
"You have chosen the following\n"
"login: " + get_data.value("_login") + "\n"
"password: " + get_data.value("password") + "\n"
"Thank you,\n"
"CompanyName Support staff\n")
msg = MIMEText(body)
msg['Subject'] = "Welcome to CompanyName Support"
msg['From'] = me
msg['To'] = get_data.value("email")
s = smtplib.SMTP('localhost')
s.sendmail(me, [you], msg.as_string())
s.quit()
set_data.exitAction(ALset.ACCEPT)
set_data.save()
action(sys.argv[1], sys.argv[2])
############################################################################
# Synopsis:
# Check if the user belongs to QA group and block closure of the ticket if
# he/she doesn't.
#
# There is no need to specify the Python interpreter if the script is named *.py
# because the system recognizes .py scripts as being Python based and will
# use the Python that is included in the distribution.
#
# If you use this script with your own copy of Python, please note that
# it requires ElementTree module to be installed
############################################################################
import sys
from ALget import ALget
from ALset import ALset
def action(inputXMLFile, outputXMLFile):
get_data = ALget(inputXMLFile)
set_data = ALset(outputXMLFile)
groups = get_data.globalVariable('my_groups')
groupAllowedToClose = "QA"
if groupAllowedToClose not in groups.split(",") and get_date.value("wfstate") == "Closed" and get_date.value("wfstate", get_date.oldRecordsNamesList()[0]) != "Closed":
# Set a field value. In this case, we set the status field
# to its old value
set_data.recordField("wfstate", get_data.value("wfstate", get_data.oldRecordsNamesList()[0]))
print("Restore state")
set_data.exitAction(ALset.ACCEPT)
set_data.save()
action(sys.argv[1], sys.argv[2])
######################################################################
# Synopsis:
# This script performs some common tasks typical of a script.
# You could run this script against the input file example:
# filename.py input.xml output.xml
#
# There is no need to specify the Python interpreter if the script is named *.py
# because the system recognizes .py scripts as being Python based and will
# use the Python that is included in the distribution.
#
# If you use this script with your own copy of Python, please note that
# it requires ElementTree module to be installed
#
######################################################################
import sys
# these are interface modules to interact with input and output xml files
from ALget import ALget
from ALset import ALset
def action(inputXMLFile, outputXMLFile):
# Load the XML files into internal structures. This is a required step before interacting with input using API calls.
get_data = ALget(inputXMLFile)
set_data = ALset(outputXMLFile)
# we will use this to accumulate messages to the user
message = ""
# Let's retrieve the user's name to provide a personalized message.
# That would be the Full Name from the Contacts table entry for the user editing the ticket.
full_name = set_data.globalVariable('my_full_name')
# Let's check if user is a creator of the record and prohibit editing if not, with an appropriate message.
# The same could be done with permissions, but access control through scripts can be more sophisticated.
# For example, you could use get_data.globalVariable('my_start_work') and get_data.globalVariable('my_stop_work')
# (if there are such fields in Contacts table) to allow modifications only within the user's working hours.
print("Editor name:" + get_data.globalVariable('my_full_name'))
print("Creator name:" + get_data.value('created_by'))
if get_data.globalVariable('my_login') != get_data.value('login'):
# We compare the login of the user who edits the record (via the global variable) with
# the login of the record's creator. Note that this example would be for the Support Cases table,
# in which the Creator Login variable is simply "login"). If they're not the same, we add a message to
# the message variable we defined earlier, to describe the reason for denial.
message += "Sorry, " + full_name + ", you are not the creator of this record, you cannot modify it."
# Then we set the exit code to reject the changes.
set_data.exitAction(ALset.BLOCK)
else:
# Now let's try to detect some changes in the record.
# For example, let's make deleteable flag non-editable without blocking other changes.
# The second parameter of value() is optional. Passing this argument in will refer to the version just before
# the user's edit. If the current (edited) version doesn't equal that version, the user must've changed it.
if get_data.value('deleteable') != get_data.value('deleteable', get_data.oldRecordsNamesList()[0]):
# We will notify user that the change is not allowed.
message += "Sorry, " + full_name + ", you cannot modify the deleteable flag, your change will be ignored."
# Let's return the old value back.
set_data.recordField('deleteable', get_data.value('deleteable', get_data.oldRecordsNamesList()[0]))
# Now some more complex techniques - linked records access.
# Let's find out, for example, the name and phone number of the record owner
# if a Support Case is "open" ("owned by" is a Linked Field relationship with the contacts table)
if "Open" == get_data.value('wfstate'):
# Retreive phone and name from first (index=0) record linked to owned_by field.
owner_phone = get_data.linkedValue("end_user_name", 0, "direct_phone")
owner_name = get_data.linkedValue("end_user_name", 0, "full_name")
message += "You can contact " + owner_name + ", owner of this support case by phone at " + owner_phone + "."
# Now check if this case is assigned to a team as opposed to a user
# NOTE: this example is outdated because the assigned_team field in support cases only links to the Teams table,
# but the methods used here are interesting regardless.
linkedRecordNames = get_data.linkedRecordsNamesList("assigned_team")
if get_data.tableNameForRecord(linkedRecordNames[0]) == "teams":
message += "This issue assigned to " + get_data.linkedValue("assigned_team", 0, "_name") + " team."
# Accept changes to ticket
set_data.exitAction(ALset.ACCEPT)
# Store the full message we've been accumulating in the variable "message" using the message() method, so the user can read it all.
set_data.message(message)
# And don't forget to save the output file.
set_data.save()
# Retrieve input and output XML files from sys.argv and pass them into our function!
action(sys.argv[1], sys.argv[2])