Catalog of procedures
Combodo's customers only
- name:
- Itop-procedure-catalog
- version:
- 1.1.0
- release:
- 2022-09-28
- description:
- Create automatically assigned Work-orders based on requested Service
- itop-version:
- 2.7
- code:
- itop-procedure-catalog
- state:
- stable
- php-version-max:
- PHP 8.1
This catalog is designed to enrich Service Management, reducing
agent's workload and errors.
With this extension, Work Orders are created
automatically for the various teams which need to
contribute to deliver each service.
Usecase
If you have a similar case, but with one of those additional needs / constrains:
-
You want to track SLA/OLA for each action
-
You need a lot of specific details for each sub-action which cannot be requested in the main ticket
-
Some of those actions must be handled by partners using Portal for Business Partner
⇒ Check Global requests management
Features
Config Manager defines templates
-
Allow to define for each Service Subcategory a set of Procedures which are required to deliver the Service.
-
A Procedure describes the task to perform and the team which will do it
-
Procedure can be ordered, as some task can be performed only when another one is completed.
Work Orders automatically created
-
When a User Request or an Incident has a Service Subcategory which has associated Procedures, then
-
Work Orders are created automatically at the first Assignment of the User Request/Incident.
-
For each Procedure, a Work order is created using the Procedure as a template (copying name, description, team and hierarchy).
-
Agents execute Work Orders in order
-
A Work Order which cannot be performed until another one is finished will appear as
pending parent
. -
When a Work Order is
closed
, then all the Work orders which were waiting for it, are automaticallyopen
and their responsible team can be notified.
Agents must close Work Orders before resolving Tickets
-
By default,
Resolve
transition is no more proposed on Ticket with work-orders created from procedures, as long as there is a non-closed Work order.
Revision History
Version | Release Date | Comments |
---|---|---|
1.1.0 | 2022-09-28 | Enabled on Incident class Prevent Ticket resolution with non-closed work orders XML nodes removed (Check migration notes) |
1.0.2 | 2022-02-09 | Add German translations (many thanks to Lars Kaltefleiter / ITOMIG) |
1.0.1 | 2019-01-22 | Alignement with the version published in the designer |
1.0.0 | 2017-02-27 | First version |
Migration notes
1.1.0
The following ExternalFields were removed from the extension default Datamodel:
Class | Removed fields |
---|---|
WorkOrder | parent_workorder_name |
Procedure | servicesubcategory_name |
service_name | |
parent_procedure_name |
1.0.0
There were 2 versions 1.0.0 of this extension, which are slightly different:
-
The one on the ITSM Designer use an ExternalKey on Procedure (it's the choice kept going forward)
-
The one on GitHub and in Legacy package use a HierarchicalKey on Procedure
Limitations
Defined for User Request and Incident Ticket only.
Customization required to use it on Changes.
Requirements
Configurator for automatic object creation extension is required
Installation
Use the Standard installation process for this extension.
Configuration
All those actions are optional, as it works out of the box, but they will improve the user experience
Simplify Procedure creation
Set this Configuration parameter, to enable easy creation of procedures from a Service subcategory
- Configuration
-
'allow_menu_on_linkset' => true,
Simplify Procedure copy
Copy this piece of code as an entry in $MyModuleSettings =
array(
of the Configuration file, to simplify duplication of
a procedure that you want to reuse on a different service
sub-category for eg.
- config.php
-
'itop-object-copier' => array ( 'rules' => array ( 'clone-procedure' => array ( 'source_scope' => 'SELECT Procedure', 'allowed_profiles' => 'Administrator,Configuration Manager', 'menu_label' => 'Clone...', 'menu_label/FR FR' => 'Cloner...', 'form_label' => 'Cloning %1$s', 'form_label/FR FR' => 'Clonage de %1$s', 'report_label' => 'Cloned from %1$s', 'report_label/FR FR' => 'Cloné depuis %1$s', 'dest_class' => 'Procedure', 'preset' => array ( 0 => 'clone_scalars(*)', 1 => 'reset(name)', ), 'retrofit' => array ( ), ),
Remove control
The extension from version 1.1.0 prevent resolution of a Ticket which is using a catalog of procedure, as long as there are associated Work Orders still not closed. It corresponds to the below configuration which comes automatically at first installation, but even if not present, it will behave this way.
- config.php
-
'itop-procedure-catalog' => array ( 'allow_open_workorder_on_resolution' => false, ),
allow_open_workorder_on_resolution
to
true
.Procedure to Workorder
The below entry to copy in $MyModuleSettings =
array(
of the configuration file , is not needed unless you
have already an entry defined for
itop-stencils
, in which case you must append it.
- config.php
-
'itop-stencils' => array ( 'rules' => array ( 'UserRequestProcedureCatalog' => array ( 'name' => 'Workorders', 'trigger_class' => 'UserRequest', 'trigger_scope' => 'SELECT UserRequest WHERE task_created="no"', 'trigger_state' => 'assigned', // triggered when reaching this state 'report_label' => 'Ticket:Info:WorkOrderCreatedFromProcedure', 'templates' => 'SELECT Procedure WHERE servicesubcategory_id = :trigger->servicesubcategory_id AND parent_procedure_id =0', 'copy_class' => 'WorkOrder', // Class of objects which will be created using the templates 'copy_actions' => array ( // Series of actions to preset the object in the creation form 0 => 'clone(name)', 1 => 'clone(description)', 2 => 'set(ticket_id,$trigger->id$)', 3 => 'set(team_id,$this->team_id$)', ), 'copy_from_trigger' => array ( ), // Applies recursively the same process on children of the template 'copy_hierarchy' => array ( 'template_parent_attcode' => 'parent_procedure_id', 'copy_parent_attcode' => 'parent_workorder_id', ), 'retrofit' => array ( 0 => 'set(private_log,Work orders have been created on this User Request using Procedures defined on [[ServiceSubcategory:$this->servicesubcategory_id$]])', 1 => 'set(task_created,yes)', ), ), 'IncidentProcedureCatalog' => array ( 'name' => 'Workorders', 'trigger_class' => 'Incident', 'trigger_scope' => 'SELECT Incident WHERE task_created="no"', 'trigger_state' => 'assigned', // triggered when reaching this state 'report_label' => 'Ticket:Info:WorkOrderCreatedFromProcedure', 'templates' => 'SELECT Procedure WHERE servicesubcategory_id = :trigger->servicesubcategory_id AND parent_procedure_id =0', 'copy_class' => 'WorkOrder', // Class of objects which will be created using the templates 'copy_actions' => array ( // Series of actions to preset the object in the creation form 0 => 'clone(name)', 1 => 'clone(description)', 2 => 'set(ticket_id,$trigger->id$)', 3 => 'set(team_id,$this->team_id$)', ), 'copy_from_trigger' => array ( ), // Applies recursively the same process on children of the template 'copy_hierarchy' => array ( 'template_parent_attcode' => 'parent_procedure_id', 'copy_parent_attcode' => 'parent_workorder_id', ), 'retrofit' => array ( 0 => 'set(private_log,Work orders have been created on this Incident using Procedures defined on [[ServiceSubcategory:$this->servicesubcategory_id$]])', 1 => 'set(task_created,yes)', ), ), ), ),
Usage
Define Procedures
If for a particular Service subcategory, multiple tasks need to
be performed in a particular order by different teams, then you
need to create Procedure objects using the new
menu: Procedures catalog
Create Procedure
Field | Purpose |
---|---|
Name | Name of the created WorkOrders |
Description | Description copied in the created WorkOrders |
Service | Pickup a Service to restrict the Service Subcategory |
Service Subcategory | Mandatory, a WorkOrder based on this Procedure will be created on UserRequest using this Service Subcategory |
Team | Team to which created WorkOrders will be dispatched |
Parent procedure | Set the parent, if that task cannot be performed until the parent one is done |
Avoid creating a loop with the parent procedure, as only loops with 1 or 2 workorders are prevented.
Results on Service Subcategory
Once you have created a few procedures, it will look this way:
Impact on Ticket
-
Create a User Request (or an Incident) on a Service Subcategory with Procedures defined. Nothing special happened to this Ticket at this stage.
-
Assign the Ticket: Workorders are automatically created
-
For each Procedure defined on the Service Subcategory a WorkOrder is created, with the same name, description and assigned team.
-
If the Procedure has a parent, then the created WorkOrder will have a corresponding parent work order.
-
When the WorkOrder as a Parent WorkOrder, its status is automatically set to
pending parent
until the parent WorkOrder is completed
Impact on resolution
From version 1.1.0 resolution of a Ticket which is using a
catalog of procedure, is not proposed as long as there are
associated Work Orders not closed.
The transition is not proposed and a message is displayed each time
the ticket is open to remind the rule.
Impact on Work Order
This extension modifies the life cycle of WorkOrder objects, by
-
adding a state
pendind_parent
, -
two automatic transitions (never proposed to users)
-
a method, to handle the fact that WorkOrder are pending the execution of their parent WorkOrder, and they can start only when their parent is closed.
Questions & Answers
Procedure on Changes?
Answer: In order to be able to use it on another Ticket class than UserRequest and Incident, that class must have at least
-
an externalKey to the Service class or an externalKey to the ServiceSubcategory class (better but one or the other works).
-
add a boolean flag field
task_created
on the Ticket class to identify Tickets on which WorkOrders have been created (if you call it differently adapt the configuration) -
then modify the configuration entry. Here I am assuming that the class Change has a
service_id
, but noservicesubcategory_id
, so those are just the modified lines:
- Configuration
-
23 => array ( 'name' => 'Tasks', 'trigger_class' => 'Change', 'trigger_scope' => 'SELECT Change WHERE task_created="no"', 'templates' => 'SELECT Procedure WHERE service_id = :trigger->service_id', //(...) 'retrofit' => array ( // the following won't work without a private_log field, use another field or remove that line // 0 => 'set(private_log,A task list has been created for the ticket)', 1 => 'set(task_created,yes)', ); );
Troubleshooting
Question: My UserRequests are moved
to assigned
state with an auto-dispatch rule, but the
WorkOrders aren't created, why?
Answer: It's a known limitation. We have
currently no workaround.
Question: What happen if I bulk
resolve 2 Tickets, one with open workorders issued from procedure,
and some not?
Answer: At first stage, iTop doesn't check if
transition is applicable to each ticket, so the transition is
proposed based on default datamodel
Then in the second screen of the bulk transition, iTop controls for each Ticket if the transition is allowed. If not the Ticket is displayed and automatically unselected and greyed.
Question: I cannot install the latest
version, it says that filter
node cannot be
redefine
Answer: If you have defined with a previous
version of the Procedure catalog
extension a filter on
the field parent_workorder_id
, with the ITSM Designer
or an extension, then you need to remove that filter or change its
_delta
value to force
or
redefine
.
Customization
Question: How can I force the
UserRequest to be assigned to the team in charge of the last
activated WorkOrder
Answer: If your WorkOrders are all sequential,
assigned to different teams all parts of the Customer Delivery
Model, and you want your User Request to be automatically
reassigned to the next team to work on the UserRequest, then you
can do this with an extension containing those 2 changes:
1. Create a PHP function updating the User Request:
- class:WorkOrder
-
public function DispatchParentTicket() { $oTicket = MetaModel::GetObject('Ticket', $this->Get('ticket_id'), false); $oNewTeam = $this->Get('team_id'); if ($oTicket && $oTicket->Get('team_id') != $oNewTeam) { $oTicket->Set('team_id', $oNewTeam); // This will trigger notification and empty the agent_id // This can fails if this stimulus is not applicable in the current state $oTicket->ApplyStimulus('ev_dispatch'); $oTicket->DBUpdate(); } return true; }
2. Call that function when a WorkOrder is reactivated:
- itop-design / classes
-
<class id="WorkOrder" _delta="must_exist"> <lifecycle> <states> <state id="pending_parent" _delta="must_exist"> <transitions> <transition id="ev_start" _delta="must_exist"> <actions _delta="redefine"> <action> <verb>SetCurrentDate</verb> <params> <param xsi:type="attcode">start_date</param> </params> </action> <action> <verb>DispatchParentTicket</verb> </action> </actions> </transition> </transitions> </state> </states> </lifecycle>
Limitations
-
If multiple WorkOrders were waiting for the same parent, the UserRequest will be re-dispatched successively to each of the teams
-
If the team associated with the WorkOrder is not part of the Customer Delivery Model, it will still be affected to the User request
-
If the User Request is not in a state which supports the
ev_dispatch
stimulus, the team will be changed but neither the state nor the agent.
Question: Can I prevent resolution of
Ticket as soon as there is a non-closed Work Order?
Answer: Yes, out of the box, this prevention is
limited to Ticket with Work Order created by Procedure, but you can
change this by removing in the below method, the tests on
task_created
:
- class:Ticket
-
public function CountBlockingWorkorder() { $iUnclosed = 0; if (!MetaModel::GetModuleSetting('itop-procedure-catalog', 'allow_open_workorder_on_resolution', false) && MetaModel::IsValidAttCode(get_class($this),'task_created') && ($this->Get('task_created') == 'yes')) { $sOQL = "SELECT WorkOrder WHERE ticket_id=:ticket_id AND status!='closed'"; $oWorkOrderSet = new DBObjectSet(DBObjectSearch::FromOQL($sOQL),[],['ticket_id' => $this->GetKey()]); $iUnclosed = $oWorkOrderSet->Count(); } return $iUnclosed; }
The above method is called
-
Each time the valid transitions of a UserRequest or an Incident are computed.
If that method returns a number strictly above 0, theev_resolve
transition is removed, and a message is displayed to the User. -
It is also called, if a user requests a transition, ending on
resolve
state.
Again if the above method returns that there are blocking Work orders, then the transition is blocked (The error message displayed isn't userfriendly, but this is an iTop core issue)