This module provides the capability to add dynamically additional fields on a User Request in order to better qualify it. The additional fields proposed will be different based on the selected Service / Service Subcategory.
For instance when a user asks for a “new virtual machine”, then we may want him to provide the number of CPUs, the quantity of RAM and the type of OS in structured fields rather than hoping that the user will provide them by himself, in the Description
field.
You just have to define your template and then when a user creates a ticket, the additional fields will appear in the ticket edition form, based on the selected service subcategory.
A request template is related to a service subcategory. A request template can add one or multiple additional fields to User Requests. The additional fields can be of the following types:
Release Date | Version | Comments |
---|---|---|
2020-12-02 | 2.1.5 | * Fix wrong module version for template-base and itop-request-template-portal * Fix incompatibility with Request Template, for iTop with a portal different than the standard portal * Fix request template indexing CLI (encoding/truncate issue) |
2020-07-15 | 2.1.4 | * Fix issue calling TruncateFieldValue in TemplateValue::Set |
2020-04-29 | 2.1.2 | Template field generation script now handle correctly deleted request templates |
2020-03-26 | 2.1.1 | - Fix regression when submitting with transition form - Fix remove TemplateFieldValue on object deletion |
2019-12-04 | 2.1.0 | - Request template fields are now queryable - Fix missing menus on request template view - Update DE translations |
2019-01-30 | 2.0.14 | Fix regression introduced in 2.0.10: custom date formats no longer working |
2018-12-19 | 2.0.13 | - Fix unnecessary error messages popping on the screen when a DoCheckToWrite fails - Fix execution notice (check array existence) - Update spanish translations (thanks to Miguel Turrubiates!) |
2018-06-27 | 2.0.12 | Add DE translation |
2018-06-26 | 2.0.11 | ES + BR translations, default search attributes |
2018-01-26 | 2.0.10 | Ticket fields can now be used in customized forms. Also fixed 2 bugs for usage in notifications templates ($service_details$) : - N°1079 When the user leaves it undefined, then this is shown as an error message in the email: “Custom field error: Wrong format: missing template_data” ; - N°1080 When a field aims at selecting an object, the email body shows the id of the selected object. |
2018-01-05 | 2.0.9 | Customized forms are now compatible with Incident |
2017-11-13 | 2.0.8 | Service_details is now documented on UserRequest creation before notification |
2017-09-08 | 2.0.7 | Request template value not set in notification when creating an object |
2017-03-01 | 2.0.6 | Added module setting to reset template fields value when changing to a different template that contains fields with same codes |
2016-12-13 | 2.0.5 | Fixed issues when used in cunjunction with the legacy portal. Requires iTop > 2.3.2 for the date/time pickers to work fine |
2016-11-29 | 2.0.4 | Implemented placeholders (e.g. $this->html(service_details)$. Requires iTop > 2.3.1 for the placeholders to work fine. |
2016-09-08 | 2.0.3 | Added validation pattern to Date and DateTime fields. Fixed a PHP Warning when launching the cron manually. |
2016-09-02 | 2.0.2 | Hidden and Read-only fields are now rendered like multiline strings (like a textarea, though it is read-only) - Note that this will work fine in the console with iTop 2.3.0+, but requires iTop > 2.3.1 to take advantage of this enhancement in the enhanced customer portal (no change in the legacy portal!) |
2016-08-03 | 2.0.1 | Support of the console and the enhanced customer portal (both require iTop 2.3.0, otherwise the behavior is the same as 1.0.5) |
2015-11-26 | 1.0.5 | Fix for crash when submitting a ticket from the portal for a template with an ENUM field containing some special characters. |
2015-09-29 | 1.0.4 | Fix for a crash when a “drop-down list” field contains some weird characters (accents, question marks…) at the beginning of the list of values. |
2014-12-10 | 1.0.3 | Cosmetics on the module name. |
2014-04-03 | 1.0.2 | Minor fix to allow non admin users to import Template fields in CSV. |
2014-03-10 | 1.0.1 | Bug fix for template fields with the same name as an attribute of the object. |
2014-02-05 | 1.0.0 | First version, never validated. |
team_name
), as the proposed values won't be refreshed upon a change of team. Classical external fields you may be tempted to use but should not: caller_name
, org_name
, agent_name
, team_name
, service_name
, servicesubcategory_name
. See Q&A: Values not refreshed for examples and workaround.Show obsolete data
user preference is not taken into account. If you don't want obsolete objects to be proposed, put it in your query. service_details
field)service_details
field)Use the Standard installation process for this extension.
Upgrade: In order to be able to search for old User Requests which do have a particular value set in a request template, the iTop administrator need to run once a special page which explode every (User Request) template data into new tables, so it can be queried with OQL.
php populateTemplateFieldValue.php --append
You can either use “--append” or “--reset”, same results, might differ in execution time.
The following settings can be adjusted in the iTop configuration file, in the section itop-request-template
:
Parameter | Type | Description | Default Value |
---|---|---|---|
copy_to_log | string | The attribute into which the template values should be copied. Set to an empty string to disable this behavior. | public_log |
The following settings can be adjusted in the iTop configuration file, in the section templates-base
:
Parameter | Type | Description | Default Value |
---|---|---|---|
hidden_fields_profiles | string | CSV list of profiles. If the user has ANY of the listed profile, she will NOT see the fields of type “hidden”. | Portal user |
reset_fields_on_template_change | boolean | If set to “true”, fields value will be reset when changing template, even if some of the fields have the same code. | false |
view_extra_data | string | ![]() | relations |
From the Service Management menu, click on “Request template”:
The pages show a list of already defined request templates. Click on the button “new” to create a new one:
A request template is identified by its name the related service and service sub category.
The label is used on the portal to select a template if several are defined for a given service sub category.
The tab “Fields” is used to define the fields of the template:
Click on “Create a new field” to define a new one:
Here is a complete description of the properties:
Property | Description | Example |
---|---|---|
Code | Unique identifier, that can be used in the queries defined in another field. This value must be made of alphanumeric characters and cannot start with a number | model |
Order | An integer that defines in which order the fields are displayed in the form | 3 |
Label | Label seen by the user who is prompted for entering a value | Device Model |
Mandatory | Wether or not the user must enter/select a value | yes |
Input type | … see a detailed description hereabove | List |
Values (OQL or CSV) | Used for drop-down lists only to define the list of allowed values for this element. This can be either a comma separated list of values (e.g. “high,medium,low ”). The OQL can have a parameter in the form :template->code , where code is the code of another field. It can also use placeholder like :current_contact->org_id or :this->org_id which refer to the customer of the Ticket | SELECT Model WHERE brand_id = :template->brand |
Initial value | Used to set an initial value for text or text area fields | xyz |
Format | Allows you to define a regular expression for validating text fields | ^[a-zA-Z]$ |
To limit to … | use this regex within Format |
an email | [a-zA-Z0-9._&'-]+@[a-zA-Z0-9.-]+\.[a-zA-Z0-9-]{2,} |
a phone number | ^\+?[0-9\ ]{8,20}$ |
a url | https?,ftp)\://([a-zA-Z0-9+!*(),;?&=\$_.-]+(\:[a-zA-Z0-9+!*(),;?&=\$_.-]+)?@)?([a-zA-Z0-9-.]{3,})(\:[0-9]{2,5})?(/([a-zA-Z0-9%+\$_-]\.?)+)*/?(\?[a-zA-Z+&\$_.-][a-zA-Z0-9;:[\]@&%=+/\$_.-]*)?(#[a-zA-Z_.-][a-zA-Z0-9+\$_.-]*)? |
The input type can have one of the following values:
Input type | Description |
---|---|
Date | A pure date, entered by the mean of a calendar, or directly typed in |
Date and time | Date and time, entered by the mean of a calendar, or directly typed in |
Drop-down list | A list as defined by the property Values |
Duration | A time lapse |
Hidden | A value that will not be seen by the end-user (customer portal), but it will be seen by an agent (console) in modification only. The value is set by the mean of the property Initial value |
List | A value to select amongst a list of proposed values. These values are defined by the mean of the property Values … |
Read-only | A value defined in Initial value, and which cannot be modified by anybody |
Text | A single line of text, which format may be enforced by setting Format |
Text area | A text with several lines |
The tab “Preview” displays a preview of the template as it will be displayed in the console:
If a end-user selects a service sub-category on the customer portal which is related to a request template, the specific fields for this template are displayed, grouped under the denomination Service details.
This additional information is copied into the Public log when the User Request is created:
It is also possible for a Support Agent to see or edit the information in the details of the User Request, from the console:
In a notification template, or anywhere else where a template can be used, the following placeholders will be available.
Assuming that this is a UserRequest:
Hidden fields are forcibly excluded from the placeholders.
When a template value corresponds to an object selected into iTop, the returned value will be the friendly name of the object.
Question: Can I get the UserRequest which do not have a associated Request Template
Answer: Yes & No.
Query like this will fails
SELECT UserRequest WHERE ISNULL(service_details) = 1
While such query will work, with the limitation that if you have added or removed Request Template to service subcategories after the creation of User Request using those service Subcategories, then the result will be wrong.
SELECT u,rt FROM UserRequest AS u JOIN ServiceSubcategory AS ss ON u.servicesubcategory_id=ss.id JOIN RequestTemplate AS rt ON rt.servicesubcategory_id=ss.id WHERE ISNULL(rt.name) = 1
Question: Can I search for UserRequest which do have a particular value in a field of the associated Request Template
Answer: Yes with a recent enough version (above 2.1.0)
SELECT UserRequest AS u JOIN TemplateFieldValue AS v ON v.obj_key=u.id WHERE v.template_name="Laptop ordering" AND field_code='size' AND field_value='wide'
You must specify the name (or id) of the Request Template, as the field_code
may not be sufficient to identify uniquely a particular template, the same code could be used on multiple Templates.
SELECT u,m FROM UserRequest AS u JOIN TemplateFieldValueLnk AS v ON v.obj_key=u.id JOIN Model AS m ON v.field_target_key = m.id WHERE v.template_name="Desktop ordering details" AND field_code='model' AND field_target_class='Model'
Question: Can I search for UserRequest which do have a particular value in a Request Template field and another value in another Request Template field?
Answer: Yes, also it's tricky and as above requires a recent enough version of the extension (above 2.1.0) - Thanks to Synairgis Inc
for reporting this limitation
Usecase: Retrieve the UserRequest which have a Request Template named “test” and all those particular values in their Request Template fields:
Here is the non-working query, followed by the workaround
SELECT UserRequest AS u JOIN TemplateFieldValue AS v1 ON v1.obj_key=u.id JOIN TemplateFieldValue AS v2 ON v2.obj_key=u.id JOIN TemplateFieldValue AS v3 ON v3.obj_key=u.id WHERE (v1.template_name="test" AND v1.field_code="profile" AND v1.field_value="1") AND (v2.template_name="test" AND v2.field_code="contract" AND v2.field_value="a") AND (v3.template_name="test" AND v3.field_code="site" AND v3.field_value="Bordeaux")
SELECT UserRequest AS u JOIN TemplateFieldValue AS v1 ON v1.obj_key=u.id WHERE (v1.template_name="test" AND v1.field_code="profile" AND v1.field_value="1") AND u.id IN( SELECT UserRequest AS u JOIN TemplateFieldValue AS v2 ON v2.obj_key=u.id WHERE (v2.template_name="test" AND v2.field_code="contract" AND v2.field_value="a") AND u.id IN ( SELECT UserRequest AS u JOIN TemplateFieldValue AS v3 ON v3.obj_key=u.id WHERE (v3.template_name="test" AND v3.field_code="site" AND v3.field_value="Bordeaux")))
Question: I have installed version 2.1, but OQL queries does not return old User Request.
Answer: With version 2.1.0 or above of this extension, if you want to perform queries over User Requests made prior to the deployement of this version, you have to launch once, a cli script which will explode the data created before into the new queryable objects.
The command requires to be on iTop server using the web
user:
cd /path/to/itop/ cd env-production/templates-base/ php populateTemplateFieldValue.php --append
This command explodes not-yet-exploded CustomAttribute data into new objects TemplateFieldValue and TemplateFieldValueLnk.
Note: An alternate mode is php populateTemplateFieldValue.php –reset
which empty the new tables and rebuild them from scratch. Just after the upgrade to 2.1, the 2 modes are pretty similar.
Question: I want to install this extension on my own portal, how can I do it?
Answer: It requires to write an iTop extension. Add the below XML to the creation Form of the UserRequest in your own portal
<form id="ticket-create"> <twig> <div class="form_field" data-field-id="service_details"/>
Here I suppose that the id of the Ticket creation form is called “ticket-create” but any id is possible, the important piece is the data-field-id which must be exactly service_details.
Question: I have installed this extension on an iTop without itop-portal
and service_details
cannot be edited. Why?
Answer: That's an historical trick related to the old itop portal prior to version 2.3.0. Here is what the extension does:
<states> <state id="new"> <flags> <!-- If the modern portal is NOT installed, the custom fields will remain Read-Only --> <!-- Otherwise, the module itop-request-template-portal will enable the field in RW mode --> <attribute id="service_details" _delta="define"> <read_only/> </attribute> </flags> </state> </states>
to fix this you must alter the datamodel of the extension (so after it) in another extension.
<states> <state id="new"> <flags> <attribute id="service_details" _delta="delete"/> </flags> </state> </states>
Question: I want to define RequestTemplate on the “Change” class. Can I do it?
Answer: Yes, but it requires to write an iTop extension.
We assume that you have installed your iTop with “Change Simple”. It's possible to do it even on full ITIL, but a bit more complex
What is required:
service_id
and servicesubcategory_id
to the class Changeservice_details
to the class Changerequest_type
field to include “change” as a valid valueservicesubcategory_id
filter on class UserRequest to not propose change
related Service Subcategories
1) You will have to associate your Change to a Service and a Service Subcategory, as it is the ServiceSubcategory which is the link to retrieve the possible RequestTemplates applicable to an object. It is possible to do without this assumption but it's way more complex and won't be explained at all.
Check here if you don't know how to add those fields service_id
and servicesubcategory_id
to the class Change
<field id="servicesubcategory_id" xsi:type="AttributeExternalKey" _delta="define"> <sql>servicesubcategory_id</sql> <is_null_allowed>true</is_null_allowed> <on_target_delete>DEL_MANUAL</on_target_delete> <target_class>ServiceSubcategory</target_class> <filter>SELECT ServiceSubcategory WHERE request_type='change'</filter> </field>
2) you will have to add this very particular field.
<field id="service_details" xsi:type="AttributeCustomFields" _delta="define"> <handler_class>RequestTemplateFieldsHandler</handler_class> </field>
3) Of course, you need to redefine the presentation to add those 3 fields to the display of a Change object in the Console
<presentation> <details> ...
If you also have added the Change object to a portal refer to the above question for adding the request template as well on your Change in your Portal.
4) Add a change
value to the Service Subcategory class, so you can flag in your Service catalog, the Subcategory which are applicable to Change:
<field id="request_type" _delta="if_exists"> <values> <value id="change" _delta="define">change</value> </values> </field>
5) Redefine the RequestTemplate::GetTargetClass() method by the one below or something similar
public function GetTargetClass() { $iSubCategory = $this->Get('servicesubcategory_id'); $oSubCategory = MetaModel::GetObject('ServiceSubcategory', $iSubCategory); if (is_null($oSubCategory)) { throw new Exception('Missing Service Subcategory'); } $sRequestType =$oSubCategory->Get('request_type'); if (($sRequestType == 'change') && (class_exists('Change'))) { return 'Change'; } if (($sRequestType == 'incident') && (class_exists('Incident'))) { return 'Incident'; } if (class_exists('UserRequest')) { return 'UserRequest'; } throw new Exception("The selected Service Subcategory is incompatible with your installation options (request type '$sRequestType' not supported)"); }
6) Portal adaptation
You may adapt this method to enable a Change creation on iTop Portal upon selection of a ServiceSubcategory related to a Change.
That's not enough, as you will need to add scopes
, forms
and maybe brick
to manage correctly the Change in the Portal, but this is another topic.
static public function CreateFromServiceSubcategory($oServiceSubcategory) { $sType = $oServiceSubcategory->Get('request_type'); if ($sType == 'change') { if (!class_exists('Change')) { throw new Exception('Could not create a ticket after the service ' .$oServiceSubcategory->Get('friendlyname').' of type '.$sType .': unknown class "Change"'); } $oRet = new Change(); } elseif ($sType == 'incident') { if (!class_exists('Incident')) { throw new Exception('Could not create a ticket after the service ' .$oServiceSubcategory->Get('friendlyname').' of type '.$sType .': unknown class "Incident"'); } $oRet = new Incident(); } else { if (!class_exists('UserRequest')) { throw new Exception('Could not create a ticket after the service ' .$oServiceSubcategory->Get('friendlyname').' of type '.$sType .': unknown class "UserRequest"'); } $oRet = new UserRequest(); } return $oRet; }
Question: When I define possible values which depends on xxx_name
which is a Ticket field, it does not refresh.
Answer: Yes, this is a known limitation. team_name
is an ExternalField, it's not a user provided field, it is computed based on another user provided one, here team_id
. Because of an iTop limitation (still present in 3.0) dependencies on such type of field does not work. The list is not refreshed, when that field is modified.
There is a workaround, also it makes the query writing a bit more complex sometimes.
First usecase: let's assume that you want to display the servers linked to the Ticket Team
Here is the non-working version followed by the workaround
SELECT Server AS s JOIN lnkContactToFunctionalCI AS l ON l.functionalci_id=s.id WHERE l.contact_name=:this->team_name
SELECT Server AS s JOIN lnkContactToFunctionalCI AS l ON l.functionalci_id=s.id WHERE l.contact_id=:this->team_id
Second usecase: let's assume that you want to display the servers belonging to the organization of the Ticket Team
and that you have created a new ExternalField on UserRequest called teamorg_id
computed as the organization id of the team
<field id="teamorg_id" xsi:type="AttributeExternalField" _delta="define"> <extkey_attcode>team_id</extkey_attcode> <target_attcode>org_id</target_attcode> </field>
Here are the non-working version followed by the workaround
SELECT Server AS s WHERE s.org_id=:this->teamorg_id
SELECT Server AS s JOIN Organization AS o ON s.org_id=o.id JOIN Contact AS c ON c.org_id=o.id WHERE c.id=:this->team_id