If you would like to extend your own application to provide user self-service capabilities via the CPSM workflow approval platform or if you are interested in building your own custom application with a simplified user interface then this article is for you.

The objective of this article is to demonstrate how developers can query user services and workflow approval requests from the XML API. Developers can use this single-page application sample as a starting point to build their own bespoke solution, such as a mobile app or e-Commerce site powered by CPSM.

The solution is a single-page application using HTML + CSS3 + JavaScript. The following external resources were used:

Pre-requisite

Workflow approval is supported in CloudPortal Services Manager (CPSM) v11+. I recommend that administrators and developers watch my video series to discover how to enable, configure and customize workflow approval.

Workflow Approval

Workflow approval allows managers and groups of people to be notified when an action occurs or when a request is made that is likely going to affect billing.

For example, George is a solicitor that is about to start on a new project with frequent email correspondence. George would like to subscribe to a new 50GB mailbox service, which will cost $19 per month.

The company policy is that all employee expenses must be approved by a manager and the accounts department. The IT department can enable and configure workflow approval to notify managers and groups when users make service requests. See the managers and groups configuration videos.

George is now able to manage his own services by subscribing to a new mailbox account. CPSM will automatically notify George’s manager and the accounts department to accept or reject the request for the new mailbox.

The mailbox will be created once George’s manager and the accounts department have accepted the request. George will receive a notification when the request was accepted or rejected.

XML API

The XML API is an SDK that allows developers to interact with CPSM to perform tasks such as managing customers, users and services.

This article will use the XML API to programmatically retrieve a list of services for a user and approval requests for a customer.

Refer to the XML API documentation to view a comprehensive guide with samples to programmatically communicate with the API.

Sample Solution

The flow diagrams below outlines the core component for building a bespoke solution to manage services using workflow approval.

User Service Subscription

The following section describes the steps required for a user to request a new service.

1. A user uses the HTML page to retrieve a list of available services.

The following services are displayed for the user on the CPSM portal:

Note that the “Hosted Exchange” service is in a pending approval state, the “Lync Hosted 2013” service is provisioned and the “ShareFile” service is not provisioned.

2. The HTML page uses jQuery to send an AJAX POST request with an XML “FIND user services” message to the XML API.

The XML “FIND” request to retrieve all of the services for a user with the username “jay_sample” assigned to a customer with the unique short code “sample”:

<?xml version="1.0" encoding="utf-8"?>
<request action="FIND" version="1.0">
 <customer>
   <name>sample</name>
   <user>
     <name>jay_sample</name>
     <service />
   </user>
 </customer>
</request>

The sample JavaScript / AngularJS code to retrieve the list of services for the user:
 

$scope.getServices = function () {
   // Retrieve a list of services for the user
   dataService.getServices(getApiCredentials(),
                          $('#txtUsername').val(),
                          $('#txtCustomerCode').val())
             .done(
                function (data) {
                  $('#ResponseArea').text(data);
                  // Convert the XML repsonse to JSON
                  var response = $.xml2json(data);
                  $scope.services = response.customer.user.service;
                })
             .fail(errorCallback);
};

this.getServices = function (apiCredentials, username, customerCode) {
  // Format the request to POST to the XML API
  var request = '<?xml version="1.0" encoding="utf-8"?>' +
                '<request action="FIND" version="1.0">' +
                '<customer><name>' + customerCode + '</name>' +
                '<user><name>' + username + '</name><service /></user>' +
                '</customer>' +
                '</request>';
  return getResponse(apiCredentials, request);
};

3. The XML API returns a response for the “FIND” request.

The XML “FIND” response:

<?xml version="1.0" encoding="utf-8"?>
<response version="1.0">
 <customer>
   <name>Sample</name>
   <id>29</id>
   <fullname>Sample Limited</fullname>
   <billingid />
   <primarydomain>sample.local</primarydomain>
   <status>Provisioned</status>
   <approvalpending>False</approvalpending>
   <user>
     <name>jay_Sample</name>
     <id>141</id>
     <fullname>Jay Strydom</fullname>
     <upn>jay@sample.local</upn>
     <location>Unassigned</location>
     <department>Unassigned</department>
     <status>Provisioned</status>
     <approvalpending>False</approvalpending>
     <service>
       <name>HE</name>
       &lt;fullname&gt;<strong>Hosted Exchange</strong>&lt;/fullname&gt;
       &lt;status&gt;Requested&lt;/status&gt;
       &lt;approvalpending&gt;True&lt;/approvalpending&gt;
     &lt;/service&gt;
     &lt;service&gt;
       &lt;name&gt;LyncHosted2013&lt;/name&gt;
       &lt;fullname&gt;<strong>Lync Hosted 2013</strong>&lt;/fullname&gt;
       &lt;status&gt;Provisioned&lt;/status&gt;
       &lt;approvalpending&gt;False&lt;/approvalpending&gt;
     &lt;/service&gt;
     &lt;service&gt;
       &lt;name&gt;ShareFile&lt;/name&gt;
       &lt;fullname&gt;<strong>ShareFile</strong>&lt;/fullname&gt;
       &lt;status&gt;NotProvisioned&lt;/status&gt;
       &lt;approvalpending&gt;False&lt;/approvalpending&gt;
     &lt;/service&gt;
   &lt;/user&gt;
 &lt;/customer&gt;
&lt;/response&gt;

Note that the provisioning status and approval pending status is returned in the response.

The output as displayed in the sample index.html page:

4. The XML response is converted to JSON before it is rendered to the HTML page using AngularJS.

5. The user clicks on a button to subscribe/provision the ShareFile service.

6. The HTML page uses jQuery to send an AJAX POST request with an XML “SET service” message to the XML API.

The XML “SET” request to provision the “ShareFile” service to the user:

&lt;?xml version="1.0" encoding="utf-8" ?&gt;
&lt;request action="SET" version="1.0"&gt;
 &lt;customer&gt;
   &lt;name&gt;Sample&lt;/name&gt;
   &lt;user&gt;
     &lt;name&gt;jay_sample&lt;/name&gt;
     &lt;service&gt;
       &lt;name&gt;ShareFile&lt;/name&gt;
       &lt;status&gt;<strong>Provisioned</strong>&lt;/status&gt;
     &lt;/service&gt;
   &lt;/user&gt;
 &lt;/customer&gt;
&lt;/request&gt;

Approval Requests

The following section describes the steps required for a workflow approval user to view and approve a request.

1. An approval user uses the HTML page to retrieve a list of pending approval requests that he or she needs to approve.

The list of pending workflow approval requests for the admin user in CPSM:

2. The HTML page uses jQuery to send an AJAX POST request with an XML “GET user” message to the XML API.

The XML “GET” request to retrieve a list of approval requests that the user with the username “admin_sample” would need to response to:

&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;request action="GET" version="1.0"&gt;
 &lt;customer&gt;
   &lt;name&gt;sample&lt;/name&gt;
   &lt;user&gt;
     &lt;name&gt;admin_sample&lt;/name&gt;
     &lt;approvalresponses /&gt;
   &lt;/user&gt;
 &lt;/customer&gt;
&lt;/request&gt;

The sample code to retrieve the list of pending approval requests for the customer:
 $scope.getApprovals = function () {
    // Retrieve pending approvals for the customer
    dataService.getAppovals(getApiCredentials(), $('#txtCustomerCode').val())
          .done(
                function (data) {
                  $('#ResponseArea').text(data);
                  // Convert the XML repsonse to JSON
                  var response = $.xml2json(data);
                  $scope.approvals = response.customer.approvalresponses;
                })
          .fail(errorCallback);
 };

 this.getAppovals = function (apiCredentials, customerCode) {
    var request = '&lt;?xml version="1.0" encoding="utf-8"?&gt;' +
                  '&lt;request action="GET" version="1.0"&gt;' +
                  '&lt;customer&gt;&lt;name&gt;' + customerCode + '&lt;/name&gt;' +
                  '&lt;approvalresponses /&gt;' +
                  '&lt;/customer&gt;' +
                  '&lt;/request&gt;';
    return getResponse(apiCredentials, request);
 };

3. The XML API returns a response for the “GET” request.

The XML “GET” response:

&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;response version="1.0"&gt;
 &lt;customer&gt;
   &lt;name&gt;Sample&lt;/name&gt;
   &lt;id&gt;29&lt;/id&gt;
   &lt;fullname&gt;Sample Limited&lt;/fullname&gt;
   &lt;location&gt;csm.local&lt;/location&gt;
   &lt;billingid /&gt;
   &lt;primarydomain&gt;sample.local&lt;/primarydomain&gt;
   &lt;status&gt;Provisioned&lt;/status&gt;
   &lt;approvalpending&gt;False&lt;/approvalpending&gt;
   &lt;user&gt;
     &lt;name&gt;admin_Sample&lt;/name&gt;
     &lt;id&gt;140&lt;/id&gt;
     &lt;fullname&gt;admin&lt;/fullname&gt;
     &lt;upn&gt;admin@sample.local&lt;/upn&gt;
     &lt;firstname&gt;admin&lt;/firstname&gt;
     &lt;lastname&gt;Default Lastname&lt;/lastname&gt;
     &lt;externalemail&gt;admin@sample.local&lt;/externalemail&gt;
     &lt;location&gt;Unassigned&lt;/location&gt;
     &lt;department&gt;Unassigned&lt;/department&gt;
     &lt;expires&gt;Never&lt;/expires&gt;
     &lt;locked&gt;False&lt;/locked&gt;
     &lt;enabled&gt;True&lt;/enabled&gt;
     &lt;status&gt;Provisioned&lt;/status&gt;
     &lt;approvalpending&gt;False&lt;/approvalpending&gt;
     <strong>&lt;approvalresponses&gt;</strong>
       <strong>&lt;approvalresponse&gt;</strong>
         &lt;description&gt;Provision Service 'Hosted Exchange' to User 'Jay Strydom'&lt;/description&gt;
         &lt;status&gt;Pending&lt;/status&gt;
         &lt;requestdate&gt;20131106&lt;/requestdate&gt;
         &lt;resolveddate /&gt;
         &lt;customer&gt;
           &lt;name&gt;Sample&lt;/name&gt;
           &lt;fullname&gt;Sample Limited&lt;/fullname&gt;
         &lt;/customer&gt;
         &lt;requestedbyuser&gt;
           &lt;name&gt;jay_Sample&lt;/name&gt;
           &lt;fullname&gt;Jay Strydom&lt;/fullname&gt;
           &lt;email&gt;jay@sample.local&lt;/email&gt;
         &lt;/requestedbyuser&gt;
         &lt;subscription&gt;
           <strong>&lt;id&gt;A0E398B5E74B1CC8..FF28EEA826&lt;/id&gt;</strong>
           &lt;requestdate&gt;20131106&lt;/requestdate&gt;
           &lt;resolveddate /&gt;
           &lt;status&gt;Pending&lt;/status&gt;
           &lt;reason /&gt;
           &lt;user&gt;
             &lt;name&gt;admin_Sample&lt;/name&gt;
             &lt;fullname&gt;admin&lt;/fullname&gt;
             &lt;email&gt;admin@sample.local&lt;/email&gt;
           &lt;/user&gt;
         &lt;/subscription&gt;
       &lt;/approvalresponse&gt;
     &lt;/approvalresponses&gt;
   &lt;/user&gt;
 &lt;/customer&gt;
&lt;/response&gt;

The output as displayed in the sample index.html page:

4. The XML response is converted to JSON before it is rendered to the HTML page using AngularJS.

5. The approval user clicks on a button to retrieve detailed information about the new service request that he or she needs to approve.

6. The HTML page uses jQuery to send an AJAX POST request with an XML “GET approval” message to the XML API.

The XML “GET” request to retrieve detailed information about the approval request:

&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;request action="GET" version="1.0"&gt;
 &lt;approval&gt;
 <strong>&lt;id&gt;A0E398B5E74B1CC8..FF28EEA826&lt;/id&gt;</strong>
 &lt;/approval&gt;
&lt;/request&gt;

Note that the approval ID from step 3 was used as the identifier for the approval request.

The pending approval request information displayed in CPSM:

The output as displayed in the sample index.html page:

7. The XML API returns all of the approval request information in an XML response message.

8. The XML response is converted to JSON and bound using AngularJS to display the approval request information to the approval user.

9. The approval user clicks on a button to accept the request to provision the new service.

10. The HTML page uses jQuery to send an AJAX POST request with an XML “SET” message to the XML API that will approve the request.

The XML “SET” request to approve the new service:

&lt;?xml version="1.0" encoding="utf-8"?&gt;
&lt;request action="SET" version="1.0"&gt;
 &lt;customer&gt;
   &lt;name&gt;Sample&lt;/name&gt;
   &lt;approvalresponses&gt;
     &lt;approvalresponse&gt;
       &lt;subscription&gt;
         <strong>&lt;id&gt;A0E398B5E74B1CC8..FF28EEA826&lt;/id&gt;</strong>
         &lt;status&gt;<strong>Accepted</strong>&lt;/status&gt;
         &lt;reason&gt;Enjoy the new mailbox&lt;/reason&gt;
       &lt;/subscription&gt;
     &lt;/approvalresponse&gt;
   &lt;/approvalresponses&gt;
 &lt;/customer&gt;
&lt;/request&gt;

Note that the Id, status (Accepted, Rejected) and reason can be specified when responding to an approval request.

Download

Click here to download the sample code, which provides the complete solution for the follow page: