Action Framework - Customer Actions

Introduction

Customer actions (also called Data Object actions or Unit actions) are components of the ConSol CM Action Framework. They can be performed for a customer, i.e., a contact or a company. The actions can be performed automatically by the system or manually, triggered by an engineer who has the required permissions. You might want to apply customer actions for use cases like the following:

You can use the following types of customer actions:

Please keep in mind that only engineers who have at least one role with the following access permissions for the respective customer group are allowed to use the Customer Actions, i.e., only then will the Activities be displayed in the Web Client:

Figure 198: ConSol CM Web Client - Example for manual customer activities

Customer Actions are based on Groovy scripts which are stored in the Scripts and Templates section of the Admin Tool. Scripts and templates for customers are usually referred to as data object or unit scripts.

The execution of Customer Actions can be controlled using condition scripts, i.e., you can implement a Data Object Condition Script which is run before the execution script of the customer action. The execution script is only run if this condition script returns true.

So there are two types of scripts you have to deal with when you use the ConSol CM Action Framework:

When you want to implement a customer action you have to proceed in three steps:

  1. Create a script for the customer action (either an execution script only or an execution script and a condition script).
  2. Create the customer action(s) which use(s) the script(s).
  3. Assign the customer action(s) to the customer group(s) where they should be available. You can assign the actions to contacts and/or companies of a customer group.

In the following sections, all three steps are explained in detail.

Managing Customer Actions Using the Admin Tool

In this book we will use the terms customer and customer definition. However, the corresponding scripts use the term data object and the names of the corresponding Java classes are Unit and UnitDefinition. All other Java classes which deal with customer objects are also still named Unit... Please keep that in mind if you work as both a ConSol CM administrator and programmer. Please refer to the ConSol CM Java API Doc for details.

Step 1: Write the Data Object Execution Script

Create a new Admin Tool script of type Data object action. If required, create another script of type Data object condition.

For a detailed explanation of Admin Tool scripts, please refer to section Admin Tool Scripts. For an introduction to Admin Tool scripts used for customer actions, please read section Scripts for the Action Framework: Programming Customer Actions in this chapter.

Figure 199: ConSol CM Admin Tool - Scripts for customer actions

//create and return action result that will tell the web to create a new ticket with unit as

//a main customer

def queueId = queueService.getByName("Helpdesk").getId();

Map<String, Object> valuesMap = new HashMap<String, Object>

valuesMap.put(PostActionParameter.UNIT_ID, unit.getId())

valuesMap.put(PostActionParameter.QUEUE_ID, queueId)

return unitActionScriptResultFactory.getPostAction(PostActionType.CREATE_TICKET, valuesMap)

Code example 25: Data Object Execution Script for CM version 6.9.4

// offer Create Ticket page for a new Service Desk ticket

import com.consol.cmas.core.server.service.action.PostActionType

import com.consol.cmas.common.model.ticket.Ticket

def newtic = new Ticket()

def qu = queueService.getByName("ServiceDesk")

newtic.setQueue(qu)

return actionScriptResultFactory.getPostAction(PostActionType.CREATE_TICKET, newtic, unit)

Code example 26: Data Object Execution Script for CM version 6.10

Step 2: Create Customer Action(s) Which Use the Script

Open the navigation item Actions in the navigation group Customers in the Admin Tool and add (= create) a new action object using the Add button . The same pop-up window appears for both adding and editing a customer action.

Figure 200: ConSol CM Admin Tool - Editing customer actions

In the pop-up window, the parameters for the new action have to be defined:

Save the action. You can then assign it to customer groups, as described in the following step.

Step 3: Assign Customer Actions to Customer Groups

For the customer action to become effective, you have to assign it to a customer group, at which point it will be available for all customers of this customer group. Depending on the initial definition (contact or company action), the action will be available for contacts or for companies in the customer group. To assign a customer action to a customer group, open the navigation item Customer Groups in the navigation group Customers of the Admin Tool. Select the customer group you would like to edit and click the Edit button to open the pop-up window to assign the customer actions. All customer actions which have been stored under Actions (see step 2) will be available here, each for the corresponding action type. For example, an action which has been defined for the type Update during definition (see step 2) will only be available as an Update action.

Figure 201: ConSol CM Admin Tool - Assigning customer actions to a customer group

You can assign the following action types to a customer group:

Using Customer Actions as an Engineer (User)

As an engineer (user), only the customer action type manual is relevant for you. The CREATE, UPDATE and DELETE scripts run in the background.

Manual actions are offered in the Web Client, similar to workflow activities for a ticket. Please see Example 1 in the next section.

Examples for Data Object Execution Scripts

Example 1: Simple Manual Action

A manual action is coded and stored as an Admin Tool script, then a company action is defined using the script, and the action is assigned to a customer group.

Figure 202: ConSol CM Admin Tool - Data Object Execution Script for a company action

Figure 203: ConSol CM Admin Tool - Defining the company action

Figure 204: ConSol CM Admin Tool - Assigning a company action to a customer group

The engineer can use the action manually in the Web Client.

Figure 205: ConSol CM Web Client - Using a manual company action

A script similar to the following could be used:

// check service status for a Reseller company and set new status

// this is an example for documentation purposes

 

import com.consol.cmas.common.model.customfield.enums.EnumValue

import com.consol.cmas.core.server.service.action.PostActionType

 

// ... do something, e.g., reference an external system to find the current service status of the company) ...

def ser_stat = enumService.getValueByName("service_status","ok")

 

// set the new service status for the company

unit.set("ResellerCompanyData:service_status","ok")

unitService.update(unit)

 

return actionScriptResultFactory.getPostAction(PostActionType.SUCCESS, "info.dataobject.action.success").withRefreshContent();

Code example 27: Data Object Execution Script, CM version 6.10

Example 2: New Ticket for a Customer

The following script opens the Create ticket page for the contact or company the action was performed for. The target queue is ServiceDesk, enabling a new Service Desk ticket to be created in no time for the open contact or company. For an introduction to Admin Tool scripts for the Action Framework, please read the following section.

import com.consol.cmas.common.model.scripting.unit.PostActionParameterimport

import com.consol.cmas.core.server.service.UnitActionScriptResultFactoryimport

import com.consol.cmas.common.model.scripting.unit.PostActionType

 

def queueId = queueService.getByName("ServiceDesk").getId();

Map<String, Object> valuesMap = new HashMap<String, Object>()

valuesMap.put(PostActionParameter.UNIT_ID, unit.getId())

valuesMap.put(PostActionParameter.QUEUE_ID, queueId)

return unitActionScriptResultFactory.getPostAction("createTicket", valuesMap)

Code example 28: Customer script (CM version 6.9.4)

import com.consol.cmas.core.server.service.action.PostActionType

import com.consol.cmas.common.model.ticket.Ticket

def newtic = new Ticket()

def qu = queueService.getByName("ServiceDesk")

newtic.setQueue(qu)

return actionScriptResultFactory.getPostAction(PostActionType.CREATE_TICKET, newtic, unit)

Code example 29: Customer script (CM version 6.10)

Please note that in case a ticket should be created with a company as main customer, the checkbox Company as customer must be checked for the customer data model of the respective customer group.

Scripts for the Action Framework: Programming Customer Actions

Customer actions are defined by Admin Tool scripts, i.e., by Groovy scripts which are stored in the Scripts and Templates section of the Admin Tool. The predefined object unit (i.e., an object of class Unit) is available for those scripts. Objects of the class Unit can represent a company or a contact, depending on the context.

There are two types of scripts for the Action Framework:

Data Object Execution Scripts

The actions in this script are either triggered automatically by the system operations CREATE, UPDATE, or DELETE or by a manual action of the engineer (using Activities in the Web Client).

Automatic Data Object Execution Scripts

unit.set("personalData.name", "Skywalker")

unitService.update(unit)

Code example 30: Set a value in customer data and update the unit

When you use unitService.update(unit), as in the example above, you should use a Data Object Condition Script to avoid infinite loops. See the notes in section Data Object Condition Scripts.

Manual Data Object Execution Scripts

For manual Data Object Execution Scripts you can make use of some specific methods and objects.

CM version 6.9:

CM versions 6.10 and up:

For a detailed explanation of the PostActionTypes in CM versions 6.10 and up, please refer to section Scripts for the Action Framework.

Create a Unit

(PostActionType.CREATE_UNIT) redirects the user to the create unit page. It uses the optional parameter PostActionParameter.CUSTOMER_GROUP_ID to define for which customer group a new unit has to be created and optionally the map of Data Object Group Fields (PostActionParameter.FIELDS_MAP) to fill the unit's Data Object Group Fields with the values which were passed on.

import com.consol.cmas.common.model.customfield.meta.FieldKey

import com.consol.cmas.common.model.customfield.AbstractField

import com.consol.cmas.common.model.customfield.StringField

import com.consol.cmas.common.model.scripting.unit.PostActionParameter

import com.consol.cmas.common.model.scripting.unit.PostActionType

 

Map<FieldKey, AbstractField<?>> fieldsMap = new HashMap<FieldKey, AbstractField<?>>()

FieldKey firstName = new FieldKey("customer", "firstname")

FieldKey name = new FieldKey("customer", "name")

fieldsMap.put(firstName, new StringField(firstName, "Han"))

fieldsMap.put(name, new StringField(name, "Solo"))

 

Map<String, Object> valuesMap = new HashMap<String, Object>()

valuesMap.put(PostActionParameter.CUSTOMER_GROUP_ID, unit.getCustomerGroup().getId())

valuesMap.put(PostActionParameter.FIELDS_MAP, fieldsMap)

 

return unitActionScriptResultFactory.getPostAction(PostActionType.CREATE_UNIT, valuesMap)

Code example 31: Company script which fills some unit data, CM version 6.9.4

// used for companies in MyCustomerGroup to create new contacts easily

 

import com.consol.cmas.common.model.customfield.meta.*

import com.consol.cmas.common.model.customfield.*

import com.consol.cmas.core.server.service.action.PostActionType

 

def myunit = new Unit()

 

def mycustomergroup = customerGroupService.getByName("MyCustomerGroup")

myunit.setCustomerGroup(mycustomergroup)

 

def mycustomerdefinition = unitDefinitionService.getByName("customer")

myunit.setDefinition(mycustomerdefinition)

myunit.set("company()", unit)

 

myunit.set("customer.firstname", "Han")

myunit.set("customer.name", "Solo")

 

return actionScriptResultFactory.getPostAction(PostActionType.CREATE_UNIT, myunit)

Code example 32: Company script which fills some unit data, CM version 6.10

Figure 206: ConSol CM Web Client - Manual company action

Figure 207: ConSol CM Web Client - Create Unit page opened and pre-filled by company action

Of course, the names of the Data Object Group Fields which are used in the script have to be the ones from the customer data model which has been assigned to the customer group for which a new contact should be created.

Figure 208: ConSol CM Admin Tool - Script for creating Unit page as company action

Create a Ticket

(PostActionType.CREATE_TICKET) redirects the user to a ticket creation page. It uses the optional PostActionParameter.UNIT_ID with the ID of the main customer, PostActionParameter.QUEUE_ID with the ID of the queue, and the Custom Fields map PostActionParameter.FIELDS_MAP.

// offer Create Ticket page for a new HelpDesk 1st level ticket

 

import com.consol.cmas.common.model.scripting.unit.PostActionType

import com.consol.cmas.common.model.scripting.unit.PostActionParameter

 

def queueId = queueService.getByName("HelpDesk_1st_Level").getId()

Map<String, Object> valuesMap = new HashMap<String, Object>()

valuesMap.put(PostActionParameter.UNIT_ID, unit.getId())

valuesMap.put(PostActionParameter.QUEUE_ID, queueId)

return unitActionScriptResultFactory.getPostAction(PostActionType.CREATE_TICKET, valuesMap)

Code example 33: Script creates and returns action result that will tell the Web Client to create a new ticket with unit as the main contact, CM version 6.9.4

// offer Create Ticket page for a new Service Desk ticket

 

import com.consol.cmas.core.server.service.action.PostActionType

import com.consol.cmas.common.model.ticket.Ticket

def newtic = new Ticket()

def qu = queueService.getByName("ServiceDesk")

newtic.setQueue(qu)

return actionScriptResultFactory.getPostAction(PostActionType.CREATE_TICKET, newtic, unit)

Code example 34: Script creates and returns action result that will tell the Web Client to create a new ticket with unit as the main contact, CM version 6.10

Please remember that the customer group for which the script should be applied has to be assigned to the queue where the ticket is to be created (HelpDesk_1st_Level in the example).

Figure 209: ConSol CM Web Client - Manual contact action

Figure 210: ConSol CM Web Client - Create ticket page opened and pre-filled by contact action

Open a Unit Page

(PostActionType.GOTO_UNIT) redirects to a unit page. It uses the obligatory parameter PostActionParameter.UNIT_ID with the ID of the unit.

import com.consol.cmas.common.model.scripting.unit.PostActionType

import com.consol.cmas.common.model.scripting.unit.PostActionParameter

 

Map<String, Object> valuesMap = new HashMap<String, Object>()

valuesMap.put(PostActionParameter.UNIT_ID, unit.get("company()").getId())

return unitActionScriptResultFactory.getPostAction(PostActionType.GOTO_UNIT, valuesMap)

Code example 35: Script which opens the company page, CM version 6.9.4

Example: Go to the contact detail page of an end customer and open the company detail page of the Reseller company which is responsible for this end customer. A company-contact relation has been established before. If more than one reseller relation has been defined, the first relation in the list is used.

Figure 211: ConSol CM Web Client - Customer action on contact detail page (activity opens company detail page of responsible reseller, CM version 6.10)

// Open company detail page of responsible reseller company, uses first reseller in list

// should only be executed if this relation exists. A condition script is used to check

 

import com.consol.cmas.common.service.UnitRelationDefinitionService

import com.consol.cmas.core.server.service.action.PostActionType

import com.consol.cmas.common.model.customfield.UnitRelation

 

// find responsible reseller

def unit_rel_def = unitRelationDefinitionService.getByName("ResellerDirectCustomersRelation")

 

Set<UnitRelation> res_relations = unitRelationService.getByDefinitionAndTarget(unit_rel_def, unit)

 

if (res_relations.size() > 0) {

def source_unit = res_relations.toArray()[0].getSourceUnit()

// log.info("SOURCE UNIT IS NOW " + source_unit.get("ResellerCompanyData:company_name"))

return actionScriptResultFactory.getPostAction(PostActionType.GOTO_UNIT, source_unit)

 

} else {

log.info("ERROR -- no responsible reseller unit found")

return actionScriptResultFactory.getPostAction(PostActionType.FAILURE, "action.result.failure" )

}

Code example 36: Script which opens the company page, CM version 6.10

If the action OpenResponsibleResellerPage should only be offered in the Web Client when a relation to the responsible reseller has been set, you can work with a Data Object Condition Script. It has to be created as an Admin Tool script of type Data object condition and has to be assigned to the customer action in the Actions section.

Figure 212: ConSol CM Admin Tool - Assignment of Data Object Condition Script

// Checks if reseller relation is set

 

import com.consol.cmas.common.service.UnitRelationDefinitionService

import com.consol.cmas.core.server.service.action.PostActionType

import com.consol.cmas.common.model.customfield.UnitRelation

 

// find responsible reseller

def unit_rel_def = unitRelationDefinitionService.getByName("ResellerDirectCustomersRelation")

Set<UnitRelation> res_relations = unitRelationService.getByDefinitionAndTarget(unit_rel_def, unit)

if (res_relations.size() > 0) {

return true

} else {

return false

}

Code example 37: Data Object Condition Script which checks if reseller relation is present

Open a Ticket Page

(PostActionType.GOTO_TICKET) redirects to a ticket page. It uses the obligatory parameter PostActionParameter.TICKET_ID with the ID of the ticket.

import com.consol.cmas.common.model.scripting.unit.PostActionType

import com.consol.cmas.common.model.scripting.unit.PostActionParameter

import com.consol.cmas.common.model.customfield.Unit

import com.consol.cmas.common.model.ticket.TicketCriteria

import com.consol.cmas.common.model.customfield.ListField

import com.consol.cmas.common.model.customfield.ContactReferenceField

import com.consol.cmas.common.model.customfield.UnitReferenceSearchField

import com.consol.cmas.common.model.customfield.ContactReferenceSearchField

import com.consol.cmas.common.model.customfield.meta.FieldKey

import com.consol.cmas.common.model.ticket.Ticket

import com.consol.cmas.common.model.ContactTicketRole

import com.consol.cmas.common.model.customfield.StringField

import com.consol.cmas.common.model.scripting.unit.UnitActionScriptResult

 

 

//get AM queue for search

def q_id = (workflowApi.getQueueByName("AccountManagement")).id

def q_ids = new HashSet()

q_ids.add(q_id)

 

//find AM ticket for the company

def crit = new TicketCriteria()

crit.setQueueIds(q_ids)

 

// create list field key

def contactSearchListFieldKey = new FieldKey("queue_fields","contacts")

 

// prepare list field

def contactsListField = new ListField(contactSearchListFieldKey )

 

// create member field key

def contactSearchFieldKey = new FieldKey("queue_fields","contacts_member")

 

// create unit member field with Unit and ticket main role

 

def contactsMember = new

ContactReferenceSearchField(contactSearchFieldKey, unit,

ContactTicketRole.MAIN_ROLE)

 

// put member field in Unit list field

contactsListField.addChild(contactsMember)

 

// put field(s) into the criteria

crit.setFields([contactsListField] as Set)

 

// seek and find

def foundTickets = ticketService.getByCriteria(crit)

 

if ( foundTickets ) {

def AM_tic = foundTickets.first()

def AM_tic_id = AM_tic.id

 

// go to AM ticket

Map<String, Object> valuesMap = new HashMap<String, Object>()

valuesMap.put(PostActionParameter.TICKET_ID, AM_tic_id)

return unitActionScriptResultFactory.getPostAction(PostActionType.GOTO_TICKET, valuesMap)

}

 

// Default: found nothing

return null

Code example 38: Open a ticket page in view mode, CM version 6.9

import com.consol.cmas.common.model.customfield.Unit

import com.consol.cmas.common.model.ticket.TicketCriteria

import com.consol.cmas.common.model.customfield.ListField

import com.consol.cmas.common.model.customfield.ContactReferenceField

import com.consol.cmas.common.model.customfield.UnitReferenceSearchField

import com.consol.cmas.common.model.customfield.ContactReferenceSearchField

import com.consol.cmas.common.model.customfield.meta.FieldKey

import com.consol.cmas.common.model.ticket.Ticket

import com.consol.cmas.common.model.ContactTicketRole

import com.consol.cmas.common.model.customfield.StringField

import com.consol.cmas.core.server.service.action.PostActionType

 

//get AM queue for search

def q_id = (workflowApi.getQueueByName("AccountManagement")).id

def q_ids = new HashSet()

q_ids.add(q_id)

//find AM ticket for the company

def crit = new TicketCriteria()

crit.setQueueIds(q_ids)

// Listenfeld-Key erzeugen

def contactSearchListFieldKey = new FieldKey("queue_fields","contacts")

// Listenfeld vorbereiten

def contactsListField = new ListField(contactSearchListFieldKey )

// Memberfeld-Key erzeugen

def contactSearchFieldKey = new FieldKey("queue_fields","contacts_member")

// Unit-Memberfeld mit Unit und Ticket-Hauptrolle erzeugen

// COmpany is MAIN CONTACT at the AM ticket!

def contactsMember = new ContactReferenceSearchField(contactSearchFieldKey, unit, ContactTicketRole.MAIN_ROLE)

// Member-Feld in Unit-Listenfeld stopfen

contactsListField.addChild(contactsMember)

// Feld(er) in die Kriterien stopfen

crit.setFields([contactsListField] as Set)

// Suchen und finden

def foundTickets = ticketService.getByCriteria(crit)

println "Found tickets: ${foundTickets}"

 

if ( foundTickets ) {

def AM_tic = foundTickets.first()

return actionScriptResultFactory.getPostAction(PostActionType.GOTO_TICKET, AM_tic)

}

// Default: found nothing

return null

Code example 39: Open a ticket page in view mode, CM version 6.10

When you use one of the scripts above, please keep in mind that the ticket search requires that the Data Object Group Fields of the company be indexed (annotation field-indexed = true).

Figure 213: ConSol CM Web Client - Company action available on company page (1)

Figure 214: ConSol CM Web Client - AM page opened after company action Go to AM ticket

Open a Web Page

(PostActionType.GOTO_PAGE) redirects to a URL. It uses the obligatory PostActionParameter.URL with the URL.

The following code shows a simple example with a fixed URL for each company.

import com.consol.cmas.common.model.scripting.unit.PostActionType

import com.consol.cmas.common.model.scripting.unit.PostActionParameter

 

Map<String, Object> valuesMap = new HashMap<String, Object>()

valuesMap.put(PostActionParameter.URL, unit.get("company:www"))

return unitActionScriptResultFactory.getPostAction(PostActionType.GOTO_PAGE, valuesMap)

Code example 40: Script which opens a certain web site (URL), CM version 6.9.4

// opens company's web site

import com.consol.cmas.core.server.service.action.PostActionType

 

def url = unit.get("url")

 

if (!url) {

return actionScriptResultFactory.getPostAction(PostActionType.FAILURE, "error.script.no.url")

} else {

return actionScriptResultFactory.getPostAction(PostActionType.GOTO_PAGE,url)

}

Code example 41: Script which opens a certain web site (URL), CM version 6.10

The string error.script.no.url is a label which has been defined in the navigation group Labels, as described in section Labels.

Figure 215: ConSol CM Web Client - Company action available on company page (2)

To open a fixed URL, you can use a Data Object Group Field of type string with the annotation text-type = url. This will automatically create a hyperlink. Thus, the use of the GOTO_URL parameter in Data Object Execution Scripts is only recommended when an URL is built dynamically within a script.

Data Object Condition Scripts

A Data Object Condition Script defines whether an action should be shown in the Web Client or not. It is executed before the Data Object Execution Script. If it returns false, the Data Object Execution Script will not be executed.

if(unit.getFieldValue("customer.personalData") == null) {

return true

} else {

return false

}

Code example 42: Data Object Condition Script

To put a Data Object Condition Script into operation, you have to perform the following steps:

  1. Write an Admin Tool script of type data object condition. The script has to define the conditions for the return values true and false, as demonstrated in the example above. At this point you must already know for which customer groups and data models the script will be used, to make sure you reference the correct data fields within the script.
  2. Assign the Data Object Condition Script to one or more customer action(s). This is done in the Actions section, navigation group Customers. Once in place, this specific Data Object Condition script will always be executed before the Data Object Execution Script of the same customer action.

That's it. You do not have to assign the condition script to a customer group. This happens implicitly when the respective customer action is assigned to contacts or companies of certain customer groups.

Important Groovy Objects

Object UnitActionScriptResult (CM Version 6.9)

The object UnitActionScriptResult is only taken into account for manual actions. For actions like CREATE, UPDATE, or DELETE it is not available. The UnitActionScriptResult object is created by the unitActionScriptResultFactory.getPostAction(String, Map<String, Object>) method. This class (resp. the object) is used to store information that will influence the process flow of the Web Client after the manual action has been executed. The UnitActionScriptResult object contains the manual action type, the IDs of the ticket, the unit, the queue, and the customer group. After executing the manual action, the user can be redirected to a different page.

Object actionScriptResult (CM Version 6.10 and Up)

Starting with CM version 6.10, the Action Framework offers the classes ActionScriptResult and ActionScriptResultFactory. An object (singleton) of the class ActionScriptResultFactory is available as actionScriptResultFactory in every action script, no matter which type of action script.

See section Scripts for the Action Framework for details.

The customer actions CREATE, UPDATE, and DELETE are executed in the core methods create, update, and delete of the object unitService.

Thus, if the update execution script updates the customer using the unitService.update(Unit) method then a java.lang.StackOverflowError error may be thrown because the update action will infinitely recurse. In that case a Data Object Condition Script should be used to avoid such infinite loops.