CM.Resource Pool - Resource Actions

Introduction

Resource Actions are a component of the ConSol CM Action Framework. Resource Actions are actions which can be performed for a resource, i.e., an object which is stored in the Resource Pool. 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 Resource Actions for use cases like the following:

You can use the following types of Resource Actions:

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

Figure 556: ConSol CM Web Client - Resource Action (on resource page)

Resource Actions are defined as Groovy scripts which are stored in the Script and Template section of the Admin Tool.

The execution of Resource Actions can be controlled using condition scripts, i.e., you can implement a condition script which is executed before the execution script of the Resource Action. The execution script is only executed if the condition script returns true.

So there are two types of scripts you have to deal with when you use ConSol CM Resource Actions:

When you want to implement a Resource Action you have to proceed in three steps:

  1. Create a script for the Resource Action (either an execution script only or an execution script and a condition script).
  2. Create the Resource Action(s) which use(s) the script(s).
  3. Assign the Resource Action(s) to the Resource Type(s) where they should be available.

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

Creating Resource Actions Using the Admin Tool

Step 1: Write the Resource Execution Script

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

For a detailed explanation of Admin Tool scripts in general, please refer to section Admin Tool Scripts.

Figure 557: ConSol CM Admin Tool - Resource Action script in Scripts section

// this script creates a new ticket for the resource from which the activity is executed, i.e., creates new ticket and links it to resource

// resource - ticket relation must be configured beforehand!

 

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

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

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

import com.consol.cmas.common.service.resource.*

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

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

 

println 'CreateTicketForResource.groovy started ...'

 

Ticket newtic = new Ticket()

 

Queue qu = queueService.getByName("ServiceDesk")

newtic.setQueue(qu)

 

newtic.setSubject("New Ticket for Resource: " + resource.getId())

newtic.set("helpdesk_standard.priority","low")

 

// use main contact person of the resource as main contact for the ticket

Unit maincont = new Unit()

def crit = new ResourceRelationWithTargetUnitCriteria()

crit.setResource(resource)

List<ResourceRelationWithTargetUnit> cont_list = resourceRelationService.getByCriteria(crit)

if (cont_list.size() == 0) {

//cmweb.rp.resource.action.no_contact_set has to be configured as label in the AT

return actionScriptResultFactory.getPostAction(PostActionType.FAILURE, "cmweb.rp.resource.action.no_contact_set")

} else {

def cont_rel = cont_list[0]

maincont = cont_rel.getTargetUnit()

}

 

ticketService.createWithUnit(newtic,maincont)

 

println 'New Ticket created for resource with ID' + resource.getId()

 

// link ticket to resource

 

def resRelationDefCriteria = new ResourceRelationDefinitionCriteria()

resRelationDefCriteria.addDefinitionName("PC_Desktop_to_Ticket_Relation")

def s_res_type = resource.getResourceType()

resRelationDefCriteria.addSourceResourceType(s_res_type)

resRelationDefCriteria.addTargetQueue(qu)

 

//log.info "resRelationDefCriteria = " + resRelationDefCriteria

//log.info "resRelationDefCriteria.definitionName = " + resRelationDefCriteria.getDefinitionsNames()

 

def resRelationDef = resourceRelationDefinitionService.getByCriteriaUniqueResult(resRelationDefCriteria)

def resRelation = new ResourceTicketRelation(resRelationDef, resource, newtic)

// log.info "resRelation" + resRelation

resourceRelationService.create(resRelation)

Code example 84: Resource execution script

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

To create, edit, or delete Resource Actions, open the navigation item Actions in navigation group Resources in the Admin Tool.

To create or add a new action click the Add button and fill-in the required data in the pop-up window (the pop-up window is the same for adding and for editing a resource action).

Figure 558: ConSol CM Admin Tool - Creating a Resource Action

Save the action. Then you can assign it to Resource Types. Please see following step.

Step 3: Assign Resource Actions to Resource Types

To assign pre-defined Resource Execution and/or Resource Condition Scripts to Resource Types, the respective manual and/or automatic actions have to be assigned to a Resource Type. Open the navigation item Data Models in navigation group Resources in the Admin Tool. Select the Resource Type you would like to edit and click the Edit button to open the pop-up window where you can assign the Resource Actions. An action might contain only a Resource Execution Script or a Resource Condition Script and a Resource Execution Script.

In the following example (next figure), a manual Resource Action is assigned to the resource type PC_Desktop.

Figure 559: ConSol CM Admin Tool - Assigning manual Resource Actions to a resource type

You can assign Resource Actions of the following action types:

Using Resource Actions in the Web Client (as an Engineer)

As an engineer (user), two Resource Action types are relevant for you because they are available as activities in the Web Client:

The CREATE, UPDATE, RELATION, and DELETE actions run in the background.

Programming Resource Execution and Resource Condition Scripts

Please read the section about Scripts for the Action Framework for a general introduction about important principles, classes, and methods for execution and condition scripts.

Examples for Resource Actions

Example 1: Simple Manual Action

Use case: The engineer should be able to create a new Service Desk ticket directly from a resource page of a PC. The new ticket should be related to the resource (PC). The main contact of the new Service Desk ticket should be the person who is responsible for the PC. This is implemented as resource-contact relation in the Resource Type PC_Desktops. To implement the Resource Action, perform the following steps.

Write the Resource Execution Script:

// this script creates a new ticket for the resource from which the activity is executed, i.e., creates new ticket and links it to resource

// resource - ticket relation must be configured beforehand!

 

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

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

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

import com.consol.cmas.common.service.resource.*

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

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

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

 

println 'CreateTicketForResource.groovy started ...'

 

Ticket newtic = new Ticket()

 

Queue qu = queueService.getByName("ServiceDesk")

newtic.setQueue(qu)

 

 

def subj = resource.get("PC_Desktop_Fields_basic.name")

 

// newtic.setSubject("New Ticket for Resource: " + resource.getId())

newtic.setSubject("New Ticket for Resource: " + subj)

 

newtic.set("helpdesk_standard.priority","low")

 

// use main contact person of the resource as main contact for the ticket

Unit maincont = new Unit()

def crit = new ResourceRelationWithTargetUnitCriteria()

crit.setResource(resource)

List<ResourceRelationWithTargetUnit> cont_list = resourceRelationService.getByCriteria(crit)

if (cont_list.size() == 0) {

workflowApi.addValidationError("ERRROR","No contact set!")

} else {

def cont_rel = cont_list[0]

maincont = cont_rel.getTargetUnit()

}

 

ticketService.createWithUnit(newtic,maincont)

 

println 'New Ticket created for resource with ID' + resource.getId()

 

// link ticket to resource

 

def resRelationDefCriteria = new ResourceRelationDefinitionCriteria()

resRelationDefCriteria.addDefinitionName("PC_Desktop_to_Ticket_Relation")

def s_res_type = resource.getResourceType()

resRelationDefCriteria.addSourceResourceType(s_res_type)

resRelationDefCriteria.addTargetQueue(qu)

 

log.info "resRelationDefCriteria = " + resRelationDefCriteria

log.info "resRelationDefCriteria.definitionName = " + resRelationDefCriteria.getDefinitionsNames()

 

def resRelationDef = resourceRelationDefinitionService.getByCriteriaUniqueResult(resRelationDefCriteria)

def resRelation = new ResourceTicketRelation(resRelationDef, resource, newtic)

log.info "resRelation" + resRelation

resourceRelationService.create(resRelation)

 

// go to new ticket

return actionScriptResultFactory.getPostAction(PostActionType.GOTO_TICKET, newtic)

Code example 85: Resource Execution Script for PC_Desktops to create a new Service Desk ticket for responsible PC contact

Create a Resource Action based on the script:

Figure 560: ConSol CM Admin Tool - Creating a new Resource Action

Assign the action to the correct Resource Type:

Figure 561: ConSol CM Admin Tool - Assign the Resource Action to the correct resource type

Check the functionality using the Web Client:

Figure 562: ConSol CM Web Client - Resource page with the Resource Action

Figure 563: ConSol CM Web Client - New Service Desk ticket created by the Resource Action

Figure 564: ConSol CM Web Client - Resource page with one or more ticket relations (new Service Desk ticket)

Example 2: Open a Maintenance Ticket from a Resource Using an ACF

The Action Framework offers the possibility to open an ACF (Activity Control Form) when a ticket is created. The ACF is used to gather data for the following workflow activity, i.e., the ticket can be created and moved through the first workflow step very easily. The following example demonstrates this functionality. A maintenance ticket should be created for a resource (an HP printer). During the (sub-) process, an ACF should be offered to ask for data which will then be used during the next workflow activity.

To implement the Resource Action, perform the following steps.

Write the Resource Execution Script:

// this script creates a new ticket for the resource from which the activity is executed, i.e., creates new ticket and links it to resource

// resource - ticket relation must be configured beforehand!

// CreateTicketForHP_PrinterWithACF.groovy

 

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

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

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

import com.consol.cmas.common.service.resource.*

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

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

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

import com.consol.cmas.common.service.*

 

println 'CreateTicketForHP_PrinterWithACF.groovy started ...'

 

Ticket newtic = new Ticket()

 

Queue qu = queueService.getByName("SpecialTasks")

newtic.setQueue(qu)

 

newtic.setSubject("New Ticket for HP Printer: " + resource.getId())

newtic.set("SpecialTasks_Fields.SpecialTasksPrio","normal")

 

// use main contact person of the resource as main contact for the ticket

Unit maincont = new Unit()

def crit = new ResourceRelationWithTargetUnitCriteria()

crit.setResource(resource)

List<ResourceRelationWithTargetUnit> cont_list = resourceRelationService.getByCriteria(crit)

if (cont_list.size() == 0) {

log.info("ERRROR in script CreateTicketForHP_PrinterWithACF -- No contact set!")

} else {

def cont_rel = cont_list[0]

maincont = cont_rel.getTargetUnit()

}

 

ticketService.createWithUnit(newtic,maincont)

 

println 'New Ticket created for resource with ID' + resource.getId()

 

// link ticket to resource

 

def resRelationDefCriteria = new ResourceRelationDefinitionCriteria()

resRelationDefCriteria.addDefinitionName("HP_Printer_ToTicket_Relation")

def s_res_type = resource.getResourceType()

resRelationDefCriteria.addSourceResourceType(s_res_type)

resRelationDefCriteria.addTargetQueue(qu)

 

log.info "resRelationDefCriteria = " + resRelationDefCriteria

log.info "resRelationDefCriteria.definitionName = " + resRelationDefCriteria.getDefinitionsNames()

 

def resRelationDef = resourceRelationDefinitionService.getByCriteriaUniqueResult(resRelationDefCriteria)

def resRelation = new ResourceTicketRelation(resRelationDef, resource, newtic)

log.info "resRelation" + resRelation

resourceRelationService.create(resRelation)

 

// go to new ticket, but fill ACF before

 

def executionContext = activityFormDefinitionService.getExecutionContext(newtic, "defaultScope/TaskInProgress/Aufgabe_annehmen")

 

if (!executionContext) {

return actionScriptResultFactory.getPostAction(PostActionType.FAILURE, "action.fail.wrong.activity")

}

 

// Modify entities from the execution context - not the original ones

// - since the user may still press cancel.

executionContext.ticket.add("SpecialTasks_Fields","Deadline", new Date());

 

return actionScriptResultFactory.getPostAction(PostActionType.GOTO_TICKET, newtic, executionContext);

Code example 86: Resource Execution Script which opens a ticket and uses an ACF

Create a Resource Action based on the script.

Figure 565: ConSol CM Admin Tool - Create the Resource Action for the HP Printer maintenance ticket

Assign the action to the correct Resource Type:

Figure 566: ConSol CM Admin Tool - Assigning the Resource Action to the correct resource type (HP Printer)

Check the functionality using the Web Client:

Figure 567: ConSol CM Web Client - Resource Action for HP Printer

Figure 568: ConSol CM Web Client - New maintenance ticket for resource (HP Printer), ACF

Working with the Changes Object in Resource Update Actions

Starting with CM version 6.10.5.4, it is possible to monitor the changes which have been performed during a resource update action. (The same applies to unit Update actions, explained in section Working with the Changes Object in Customer Update Actions).

To find out which changes have been performed use the object of class ResourceChanges in resource actions.

Please remember, the Update script will be executed:

There are two methods of the ResourceChanges object which provide information about the changed data:

Since the method return parameters contain rather complex components, we recommend to read the API doc of the ResourceChanges class. The following code provides an example for a script where a resourceChanges object is used.

/**

* Available script variables:

* Manual action:

* resource - Resource for which action is executed

*

* Create, Delete Action:

* resource - Resource for which action is executed

*

* Update Action:

* resource - Resource for which action is executed

* changes - ResourceChanges object containing information about changes done for resource entity

*

* Relation action:

* resource - Resource for which action is executed (resource-resource)

* relation - Relation object

* resourceExternalId - External resource id (resource, unit, ticket - ext resource)

*/

 

// Update Action Script displayPC_DesktpChangesInLog.groovy for resources in PC_Desktops

 

import com.consol.cmas.common.model.content.unit.UnitCommentEntry

import com.consol.cmas.common.model.content.unit.UnitAttachmentEntry

 

log.info 'Resource (PC_Desktop) data have been UPDATEd!'

// Are there any changes?

if (changes) {

log.info 'Yes, changes have been made to unit'

log.info 'Changes object is a ' + changes.class

}

 

// Have Custom Fields been changed? If yes - which?

if (changes.customFieldChangeInfo) {

log.info 'Yes, changes have been made to Custom Fields (Resource Fields)'

log.info changes.customFieldChangeInfo

log.info changes.customFieldChangeInfo.each { k, v ->

log.info "Changed field: ${k.groupName}/ ${k.fieldName}"

log.info "New value: ${v.value.value}"

log.info "Old value: ${v.previousValue.value}"

}

} else {

log.info 'No changes to Custom Fields'

}

 

// Have comments or attachmenst been changed? If yes - which?

 

log.info changes.contentChangeInfo

 

if (changes.contentChangeInfo){

log.info 'Yes, changes have been made in detail section'

if (changes.contentChangeInfo.value){

log.info changes?.contentChangeInfo.each { ctEntry ->

if (ctEntry?.value[0] instanceof UnitCommentEntry){

log.info 'A comment has been added.'

log.info 'Old value: ' + ctEntry?.previousValue

log.info 'New value: ' + ctEntry.value[0]?.text

log.info 'Made by the engineer ' + ctEntry.value[0]?.engineer?.name

log.info 'Creation date of the comment: ' + ctEntry.value[0]?.creationDate

} else if (ctEntry?.value[0] instanceof UnitAttachmentEntry){

log.info 'An attachment has been added.'

log.info 'Old value: ' + ctEntry?.previousValue

log.info 'New value text: ' + ctEntry.value[0]?.text

log.info 'New value file name: ' + ctEntry.value[0]?.filename

}

}

} else {

log.info 'Entry has been deleted.'

}

}

Code example 87: Resource Update script where changes are monitored and printed out to server.log

When for a resource of type PC_Desktops, the content of the two Resource Fields modell and name are modified, the following text is printed into the server.log file.

PC_DesktpChangesInLog.groovy] [Susan-] Resource (PDC_Desktop) data have been UPDATEd!

PC_DesktpChangesInLog.groovy] [Susan-] Yes, changes have been made to unit

PC_DesktpChangesInLog.groovy] [Susan-] Changes object is a class com.consol.cmas.common.model.resource.history.ResourceChanges

PC_DesktpChangesInLog.groovy] [Susan-] Yes, changes have been made to Custom Fields (Resource Fields)

PC_DesktpChangesInLog.groovy] [Susan-] {(modell,PC_Desktop_Fields_basic)=Modification{value=AbstractField{key=(modell,PC_Desktop_Fields_basic), value=Computer-0815-01}, previousValue=AbstractField{key=(modell,PC_Desktop_Fields_basic), value=Computer-0815}}, (name,PC_Desktop_Fields_basic)=Modification{value=AbstractField{key=(name,PC_Desktop_Fields_basic), value=My cool PC11}, previousValue=AbstractField{key=(name,PC_Desktop_Fields_basic), value=My cool PC}}}

PC_DesktpChangesInLog.groovy] [Susan-] Changed field: PC_Desktop_Fields_basic/ modell

PC_DesktpChangesInLog.groovy] [Susan-] New value: Computer-0815-01

PC_DesktpChangesInLog.groovy] [Susan-] Old value: Computer-0815

PC_DesktpChangesInLog.groovy] [Susan-] Changed field: PC_Desktop_Fields_basic/ name

PC_DesktpChangesInLog.groovy] [Susan-] New value: My cool PC11

PC_DesktpChangesInLog.groovy] [Susan-] Old value: My cool PC

Code example 88: Log output from the script above