You are browsing the documentation for iTop 3.0 which is not the current version.

Consider browsing to iTop 3.1 documentation

Transfer Ticket to another iTop

Prerequisite: You must be familiar with the Syntax used in Tutorials and have already created an extension.

learning:
Simple case exchange between 2 iTops
level:
Advanced
domains:
PHP, Automation
min version:
2.7.0

This example show how you can interconnect your own iTop with one of your provider or partner iTop instance, when a particular Ticket must be handled by them within their own iTop.
For this example, we will be using webhooks and rest webservices.

As always for such integration, the most important part is defining the scenarii, which must be supported. Here is the proposed scenario for our case:

  1. Identify Ticket to transfer: When one of your support agent, identify a Ticket, which must be submitted to a partner which uses iTop as their Ticketing system, the agent will move the ticket to a specific state and choose the appropriate partner.
  2. Transfer Ticket: When the Ticket enter that particular state, it triggers a iTop webhook call, to create a replicated ticket within the partner iTop
  3. Push more details: When your private log is updated, this is pushed on your partner ticket
  4. Get partner feedback: When the partner ticket public log is updated, this is mirrored within your private log
  5. Ticket resolution: When the partner ticket is resolved, this re-assign your Ticket, with the partner solution copied in your private log

For each of those 5 scenarii, we will have some steps to achieve on both iTops

Identify Ticket to transfer

For this scenario, we want to be able to identify Ticket that must be transferred and to whom. For this we need to:

Add an ExternalKey field partner_id on UserRequest, to be able to select the partner who should be handling the issue.

  • The partner, if unique, could be hardcoded, but you may have more than one partner with whom implementing this simple case exchange.
  • The <filter> will be specific to your datamodel, could be based on service and contract.
itop_design / classes / class@UserRequest / fields
        <field id="partner_id" xsi:type="AttributeExternalKey" _delta="define">
          <sql>partner_id</sql>
          <filter>SELECT Organization WHERE category='partner'</filter>
          <dependencies/>
          <is_null_allowed>true</is_null_allowed>
          <target_class>Organization</target_class>
          <on_target_delete>DEL_AUTO</on_target_delete>
          <tracking_level>all</tracking_level>
        </field>

Add a state to the UserRequest lifecycle, to identify when a Ticket is transferred:

  1. Create a new state “Pending partner” with code pending_partner
  2. Create a ev_pendingpartner stimulus and a transition to go from “Assigned” to “Pending partner”
    • That transition must prompt for a mandatory partner (partner_id) to whom the Ticket will be pushed
  3. Create ev_partnerupdate stimulus and a transition to go from “Pending partner” back to “Assigned”
    • This transition will be trigger by the partner using REST services, during the Ticket resolution

If you are not familiar with the XML syntax to add state, stimulus, transition and mandatory field on transition, check this Tutorial which does it for a different usecase.
Note that lifecycle modification is really easier for Combodo customers with the ITSM Designer.

Transfer Ticket

With iTop 2.7, you have to install the Webhook integration extension first

For this replication, in order to be able to easily update the other iTop ticket, the simplest is to store the remote ID within the UserRequest. This is to be done on booth your iTop and your partner's one. Add a textual or numeric field remote_ticketid on the UserRequest class.

itop_design / classes / class@UserRequest / fields
        <field id="remote_ticketid" xsi:type="AttributeInteger" _delta="define">
          <sql>remote_ticketid</sql>
          <default_value>0</default_value>
          <is_null_allowed>false</is_null_allowed>
          <tracking_level>all</tracking_level>
        </field>

Trigger

On the your iTop, create a Trigger (on entering a state): “Pending partner” with a filter like this

SELECT UserRequest WHERE remote_ticketid = 0

Trigger not 100% aligned to tutorial

iTop webhook call

Then create an iTop webhook call, linked to the above trigger, to replicate the Ticket on the partner iTop.

Webhook call not 100% aligned to tutorial

See Webhook usage for details of each field to specify. Here we will concentrate on 2 fields which are a bit more tricky.

Remote iTop connection

<note>Be cautious when creating the Application remote connection from the iTop webhook call object with the +
It proposes you to create a Remote application connection
But you need to create a more specific type of connection called Remote iTop connection which handles more aspects of the connection</code>

  • The partner must provide you an iTop user, with REST access, which could be limited with Allowed Organizations and Profile. Access rights must include:
    • At least read on Organization, Contact and Ticket
    • Write on UserRequest

JSON data

Here we provide the json data which allow to create a UserRequest on the Partner iTop, feeding it with information from our own Ticket which has triggered this call.
The fields of that Ticket are available by the mean of the standard Notification placeholders

  • Here we supposing that the partner iTop has an Organization named “Combodo” with a Person named “Support Combodo”. The created Ticket will uses those organization and caller. If they do not exist, the creation will fail with an error message.
  • Then we have decided to copy as-is, the original Title, Description, Public and Private log
  • We also initialize the Partner ticket remote_ticketid with the id of our own source ticket $this→id$, so he can updates us later.
{
  "operation":"core/create",
  "comment":"Ticket transfer by Combodo",
  "class":"UserRequest",
  "output_fields":"id, friendlyname",
  "fields":
  {
    "org_id":"SELECT Organization WHERE name = 'Combodo'",
    "caller_id":{"name":"Combodo","first_name":"Support"},
    "title":"$this->title$",
    "description":"$this->description$"
    "public_log":"$this->private_log$"
    "remote_ticketid":"$this->id$"
  }
}

Process response callback

This field usage is explained here.

For our usecase, we will create a public SetExternalID method on the UserRequest class, which will process the response to see if everything went well and store the id of the remote ticket, so it can be used later to update the partner ticket log.

class:UserRequest
public function SetExternalID($oResponse,$oAction)
{
   $sBodyAsJSON = $oResponse->GetBody(); 
   $aBody = json_decode($sBodyAsJSON, true); 
 
   // Consistency check
   if (false === $aBody) {
      throw new Exception('Could not process response as it is not a valid JSON string: '.$sBodyAsJSON);
   }
   // Remote creation check
   if (false === isset($aBody[‘objects’][0][key]) { 
      throw new Exception(‘Could not retrieve external ID’) ;
   }
   // If ok, copy the id of the created ticket, to reuse it later                            
   $sExternalID = $aBody['objects'][0][key];
   $this->Set('remote_ticketid', $sExternalID);
   $this->DBUpdate();
}

Push more details

When the requestor or the agent, adds information to the Ticket, we want that information to be mirrored on the Partner Ticket automatically.

Trigger

On the your iTop, create a Trigger (on object update), when Public and Private log fields are modified

Trigger not 100% aligned to tutorial

iTop webhook call

Then create another iTop webhook call, linked to the above trigger, to update the Ticket on the partner iTop.

Webhook call not 100% aligned to tutorial

It's quite similar to the previous one.

  • You can/should reuse the Connection already created.

JSON data

Note the use of $this→remote_ticketid$ which is the id of the corresponding Ticket in the other iTop

{
  "operation":"core/update",
  "comment":"Ticket update by Combodo",
  "class":"UserRequest",
  "key":"$this->remote_ticketid$"
  "output_fields":"id, friendlyname",
  "fields":
  {
    "public_log":"$this->head(private_log)$"
  }
}

Process response callback

You may write a method to capture failures and log them in your error.log

Get partner feedback

This is the symmetrical situation, when the Partner updates his Public log Ticket, we may want him to provide his reply just to your Agent in the Private log. This information, if applicable, may later be manually relayed to the caller by the agent.

For this reverse integration, this time, you must must provide to your partner an iTop user, with REST access, which must be allowed to read and update UserRequest which were transferred to him.

Partner must create on his iTop:

  • a Remote iTop connection to connect to your iTop (so your iTop url and a rest user are required)
  • a Trigger (on object update) and linked to it an iTop webhook call using the just created Remote iTop connection

For the JSON data and Process response callback, mirror what is described in the previous scenario, but pay attention to the inversion between Public and Private log

JSON data

{
  "operation":"core/update",
  "comment":"Ticket update by Partner",
  "class":"UserRequest",
  "key":"$this->remote_ticketid$"
  "output_fields":"id, friendlyname",
  "fields":
  {
    "private_log":"$this->head(public_log)$"
  }
}

Ticket resolution

When the Partner has resolved his Ticket on his iTop, we want our Ticket to be assigned back to our Agent with a comment, for communication with the caller/requestor.

On the partner iTop

Partner must create on his iTop:

  • Create a Trigger (on entering a state): “Resolved” with a filter
SELECT UserRequest WHERE remote_ticketid > 0
  • Create an iTop webhook call linked to the above trigger, to apply the ev_partnerupdate stimulus on your Ticket and update your Private log with the solution

JSON data

{
  "operation":"apply_stimulus",
  "comment":"Ticket update by Combodo",
  "class":"UserRequest",
  "key":"$this->remote_ticketid$"
  "stimulus": "ev_partnerupdate",
  "output_fields":"id, friendlyname",
  "fields":
  {
    "private_log":"$this->solution$"
  }
}

On your iTop

  • You will then probably add a Trigger (on entering a state): “Assigned”, with a filter to catch only User Request which just made this particular transition. When the filter is applied in database, the transition is not yet recorded, so the status is still the source one.
  SELECT UserRequest WHERE STATUS = 'pending_partner' 
3_0_0/customization/itop-webhook.txt · Last modified: 2022/07/21 09:57 (external edit)
Back to top
Contact us