This site contains the documentation that is relevant to older WSO2 product versions and offerings.
For the latest WSO2 documentation, visit https://wso2.com/documentation/.

Project Management in FreeAgent

The first use case in the FreeAgent business scenario is used for project  management. This page describes the relevant tasks and the operations you use in the FreeAgent connector and the other ESB connectors.

Overview

The flow for project management is illustrated in the following diagram. The ESB connectors for Base CRM and TSheets will be used to connect to each service. 

  1. Retrieve won deals from the BaseCRM API using the listDeals operation and create contacts  in the FreeAgent API using the createContact operation and also create projects in the FreeAgent API using the createProject operation and in the TSheets API (as high level job codes) using the addJobCodes operation.

FreeAgent operations
TSheets operations
Base CRM operations

Samples

Sample template for creating a project in FreeAgent according to given access credentials with other parameters
<?xml version="1.0" ?>
<!-- This template responsible for creating a project in FreeAgent
   according to given access credentials with other parameters -->
<template name="createProject" xmlns="http://ws.apache.org/ns/synapse">
   <!-- FreeAgent related template parameters -->
   <parameter name="freeagent.apiUrl" description="Base endpoint URL of FreeAgent API." />
   <parameter name="freeagent.accessToken" description="Access token to access the FreeAgent API." />
   <parameter name="freeagent.contactFirstName" description="First name of the individual contact." />
   <parameter name="freeagent.contactLastName" description="Last name of the individual contact." />
   <parameter name="freeagent.contactOrganisationName" description="Organisation name of the contact." />
   <parameter name="freeagent.currency" description="Currency type of the project." />
   <parameter name="freeagent.projectName" description="Name of the project." />
   <!-- Common template parameters -->
   <parameter name="id" description="ID of the deal." />
   <sequence>
      <!-- FreeAgent related template properties -->
      <property name="freeagent.apiUrl" expression="$func:freeagent.apiUrl" />
      <property name="freeagent.accessToken" expression="$func:freeagent.accessToken" />
      <property name="freeagent.contactFirstName" expression="$func:freeagent.contactFirstName" />
      <property name="freeagent.contactLastName" expression="$func:freeagent.contactLastName" />
      <property name="freeagent.contactOrganisationName" expression="$func:freeagent.contactOrganisationName" />
      <property name="freeagent.projectBudgetUnit" expression="$func:freeagent.projectBudgetUnit" />
      <property name="freeagent.currency" expression="$func:freeagent.currency" />
      <property name="freeagent.projectName" expression="$func:freeagent.projectName" />
      <!-- Common template properties -->
      <property name="id" expression="$func:id" />
      <!-- Process freeagent operations, only if freeagent accessToken provided -->
      <filter source="boolean(get-property('freeagent.accessToken'))" regex="true">
         <then>
            <freeagent.init>
               <apiUrl>{$ctx:freeagent.apiUrl}</apiUrl>
               <accessToken>{$ctx:freeagent.accessToken}</accessToken>
            </freeagent.init>
            <filter xpath="get-property('freeagent.contactOrganisationName')!=''">
               <then>
                  <!-- Call FreeAgent createContact method with organization name -->
                  <freeagent.createContact>
                     <organisationName>{$ctx:freeagent.contactOrganisationName}</organisationName>
                  </freeagent.createContact>
               </then>
               <else>
                  <!-- Call FreeAgent createContact method with first name and last name -->
                  <freeagent.createContact>
                     <firstName>{$ctx:freeagent.contactFirstName}</firstName>
                     <lastName>{$ctx:freeagent.contactLastName}</lastName>
                  </freeagent.createContact>
               </else>
            </filter>
            <filter source="$axis2:HTTP_SC" regex="201">
               <then>
                  <property name="freeagent.contact" expression="json-eval($.contact.url)" />
                  <!-- Call FreeAgent createProject method to create a new project -->
                  <freeagent.init>
                     <apiUrl>{$ctx:freeagent.apiUrl}</apiUrl>
                     <accessToken>{$ctx:freeagent.accessToken}</accessToken>
                  </freeagent.init>
                  <freeagent.createProject>
                     <contact>{$ctx:freeagent.contact}</contact>
                     <name>{$ctx:freeagent.projectName}</name>
                     <status>Active</status>
                     <budgetUnit>Hours</budgetUnit>
                     <currency>{$ctx:freeagent.currency}</currency>
                  </freeagent.createProject>
                  <filter source="$axis2:HTTP_SC" regex="201">
                     <then>
                        <property name="projectUrl" expression="json-eval($.project.url)" />
                        <script language="js">
                        	<![CDATA[ 
                             var projectUrl = ''+mc.getProperty('projectUrl');
                             var projectId =projectUrl.substring(projectUrl.lastIndexOf('/')+1, projectUrl.length);
                             
                             mc.setProperty("projectId", projectId);            
                        	]]>
                        </script>
                        <property name="status" value="Success" />
                        <property name="message"
                           expression="fn:concat('Project was successfully created with the project ID [',get-property('projectId'),'].')" />
                        <call-template target="responseHandlerTemplate">
                           <with-param name="id" value="{$ctx:id}" />
                           <with-param name="activity" value="freeagent_createProject" />
                           <with-param name="status" value="{$ctx:status}" />
                           <with-param name="message" value="{$ctx:message}" />
                        </call-template>
                     </then>
                     <else>
                        <property name="status" value="Error" />
                        <property name="message" expression="json-eval($.)" />
                        <call-template target="responseHandlerTemplate">
                           <with-param name="id" value="{$ctx:id}" />
                           <with-param name="activity" value="freeagent_createProject" />
                           <with-param name="status" value="{$ctx:status}" />
                           <with-param name="message" value="{$ctx:message}" />
                        </call-template>
                     </else>
                  </filter>
               </then>
               <else>
                  <property name="status" value="Skipped" />
                  <property name="message" value="Contact creation failed in FreeAgent." />
                  <call-template target="responseHandlerTemplate">
                     <with-param name="id" value="{$ctx:id}" />
                     <with-param name="activity" value="freeagent_createProject" />
                     <with-param name="status" value="{$ctx:status}" />
                     <with-param name="message" value="{$ctx:message}" />
                  </call-template>
               </else>
            </filter>
         </then>
      </filter>
   </sequence>
</template>


Sample proxy for retrieving won deals from Base CRM and creating new projects with a new contacts in FreeAgent and adding job codes in TSheets
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="freeagent_retrieveWonDealsAndCreateProjectsAndJobCodes" transports="https"
   statistics="disable" trace="disable" startOnLoad="true">
   <target>
      <inSequence onError="faultHandlerSeq">
         <!--BaseCRM Properties -->
         <property name="basecrm.apiUrl" expression="json-eval($.baseCrmApiUrl)" />
         <property name="basecrm.email" expression="json-eval($.baseCrmEmail)" />
         <property name="basecrm.password" expression="json-eval($.baseCrmPassword)" />
         <!-- FreeAgent Properties -->
         <property name="freeagent.apiUrl" expression="json-eval($.freeAgentApiUrl)" />
         <property name="freeagent.accessToken" expression="json-eval($.freeAgentAccessToken)" />
         <!-- TSheets Properties -->
         <property name="tsheets.apiUrl" expression="json-eval($.tSheetsApiUrl)" />
         <property name="tsheets.accessToken" expression="json-eval($.tSheetsAccessToken)" />
         <!-- Call BaseCRM listDeals method to retrieve won deals -->
         <basecrm.init>
            <email>{$ctx:basecrm.email}</email>
            <responseType>json</responseType>
            <apiUrl>{$ctx:basecrm.apiUrl}</apiUrl>
            <password>{$ctx:basecrm.password}</password>
         </basecrm.init>
         <basecrm.listDeals>
            <stage>won</stage>
         </basecrm.listDeals>		 
         <filter source="$axis2:HTTP_SC" regex="200">
            <then>
               <property name="deal.count" expression="count(//jsonArray/jsonElement/deal)" scope="operation" />
               <property name="deal.index" value="0" scope="operation" />			   
               <filter xpath="get-property('operation','deal.count')=0">
                  <then>
                     <property name="id" value="{}" />
                     <property name="status" value="Skipped" />
                     <property name="message" value="No won deals to process." />
                     <call-template target="responseHandlerTemplate">
                        <with-param name="id" value="{$ctx:id}" />
                        <with-param name="activity" value="basecrm_retrieveWonDeals" />
                        <with-param name="status" value="{$ctx:status}" />
                        <with-param name="message" value="{$ctx:message}" />
                     </call-template>
                     <loopback />
                  </then>
                  <else>
                     <!--FOR EACH deals : BEGIN -->
                     <iterate continueParent="true" id="dealsIterator" preservePayload="true"
                        expression="//jsonArray/jsonElement/deal" sequential="true">
                        <target>
                           <sequence>
                              <property name="dealId" expression="//deal/id/text()" />
                              <property name="id" expression="fn:concat('deal_id:',get-property('dealId'))" />
                              <property name="project.name" expression="//deal/name/text()" />
                              <property name="freeagent.currency" expression="//deal/currency/text()" />
                              <property name="freeagent.contactOrganisationName" expression="//deal/company/name/text()" />
                              <filter
                                 xpath="get-property('freeagent.contactOrganisationName')=null or get-property('freeagent.contactOrganisationName')=''">
                                 <then>
                                    <property name="deal.contactName" expression="//deal/main_contact/name/text()" />
                                    <script language="js">
									<![CDATA[ 
                                       var contactName = mc.getProperty('deal.contactName');
                                       var contactArray = contactName.split(" ");									   
                                       mc.setProperty("freeagent.contactFirstName", contactArray[0]);                                        
                                       if(contactArray.length>1){
                                          mc.setProperty("freeagent.contactLastName", contactArray[1]); 
                                       }
                                    ]]>
                                    </script>
                                 </then>
                              </filter>
                              <!-- Call createProject template to create projects in FreeAgent API -->
                              <call-template target="createProject">
                                 <!-- parameter values will be passed on to a sequence template -->
                                 (
                                 <with-param name="id" value="{$ctx:id}" />|
                                 <with-param name="freeagent.apiUrl" value="{$ctx:freeagent.apiUrl}" />|
                                 <with-param name="freeagent.accessToken" value="{$ctx:freeagent.accessToken}" />|
                                 <with-param name="freeagent.contactFirstName" value="{$ctx:freeagent.contactFirstName}" />|
                                 <with-param name="freeagent.contactLastName" value="{$ctx:freeagent.contactLastName}" />|
                                 <with-param name="freeagent.contactOrganisationName" value="{$ctx:freeagent.contactOrganisationName}" />|
                                 <with-param name="freeagent.currency" value="{$ctx:freeagent.currency}" />|
                                 <with-param name="freeagent.projectName" value="{$ctx:project.name}" />|
                                 ) *
                              </call-template>
                              <payloadFactory media-type="json">
                                 <format>
                                    {
                                       "jobCode":{
                                          "name": "$1",
                                          "short_code": "$2"
                                       }
                                    }
                                 </format>
                                 <args>
                                    <arg expression="get-property('project.name')" />
                                    <arg expression="get-property('dealId')" />
                                 </args>
                              </payloadFactory>
                              <property name="jobCode" expression="json-eval($.jobCode)" />
                              <property name="tsheets.jobCodes"
                                 expression="fn:concat(get-property('operation', 'tsheets.jobCodes'),get-property('jobCode'),',')"
                                 scope="operation" />
                              <property name="wonDealsIdObject"
                                 expression="fn:concat(get-property('operation', 'wonDealsIdObject'),get-property('dealId'),',')"
                                 scope="operation" />
                              <property name="deal.index" expression="get-property('operation','deal.index') + 1"
                                 scope="operation" />
                           </sequence>
                        </target>
                     </iterate>
                     <!--FOR EACH deals : END -->
                     <filter xpath="get-property('operation', 'deal.count') = get-property('operation', 'deal.index')">
                        <then>
                           <property name="tsheets.jobCodes"
                              expression="fn:substring(get-property('operation','tsheets.jobCodes'), 1, fn:string-length(get-property('operation','tsheets.jobCodes'))-1)"
                              scope="operation" />
                           <payloadFactory media-type="json">
                              <format>
                                 {
                                    "data": [$1]
                                 }
                              </format>
                              <args>
                                 <arg expression="get-property('operation','tsheets.jobCodes')" />
                              </args>
                           </payloadFactory>
                           <property name="tsheets.jobCodes" expression="json-eval($.data)" />
                           <!-- Call TSheets addJobCodes method to create a new job code -->
                           <tsheets.init>
                              <apiUrl>{$ctx:tsheets.apiUrl}</apiUrl>
                              <accessToken>{$ctx:tsheets.accessToken}</accessToken>
                           </tsheets.init>
                           <tsheets.addJobCodes>
                              <jobCodes>{$ctx:tsheets.jobCodes}</jobCodes>
                           </tsheets.addJobCodes>
                           <property name="wonDealsIdObject"
                              expression="fn:substring(get-property('operation','wonDealsIdObject'), 1, fn:string-length(get-property('operation','wonDealsIdObject'))-1)"
                              scope="operation" />
                           <property name="id"
                              expression="fn:concat('{deal_ids:[',get-property('operation','wonDealsIdObject'),']}')" />
                           <filter source="$axis2:HTTP_SC" regex="200">
                              <then>
                                 <property name="jobCodeCount" expression="count(//results/jobcodes/*)" scope="operation" />
                                 <property name="jobCodeIndex" value="0" scope="operation" />
                                 <iterate continueParent="true" id="jobCodesIterator" preservePayload="true"
                                    expression="//results/jobcodes/*" sequential="true">
                                    <target>
                                       <sequence>
                                          <property name="jobcode.statusCode" expression="//_status_code" />
                                          <property name="jobcode.statusMessage" expression="//_status_message" />
                                          <property name="jobcode.short_code" expression="//short_code" />
                                          <property name="jobcode.id" expression="//id" />
                                          <property name="jobcode.statusExtraMessage" expression="//_status_extra" />
                                          <filter source="get-property('jobcode.statusCode')" regex="^[^2][0-9][0-9]">
                                             <then>
                                                <payloadFactory media-type="json">
                                                   <format>
                                                      {
                                                         "jobCode":
                                                         {
                                                            "statusMessage": $1,
                                                            "message":$2
                                                         }
                                                      }
                                                   </format>
                                                   <args>
                                                      <arg expression="get-property('jobcode.statusMessage')" />
                                                      <arg expression="get-property('jobcode.statusExtraMessage')" />
                                                   </args>
                                                </payloadFactory>
                                             </then>
                                             <else>
                                                <payloadFactory media-type="json">
                                                   <format>
                                                      {
                                                         "jobCode":
                                                         {
                                                            "dealId":$1,
                                                            "jobCodeId": $2,
                                                            "statusMessage": "$3"
                                                         }
                                                      }
                                                   </format>
                                                   <args>
                                                      <arg expression="get-property('jobcode.short_code')" />
                                                      <arg expression="get-property('jobcode.id')" />
                                                      <arg expression="get-property('jobcode.statusMessage')" />
                                                   </args>
                                                </payloadFactory>
                                             </else>
                                          </filter>
                                          <property name="jobCodeObject" expression="json-eval($.jobCode)" />
                                          <property name="jobCodesString" expression="fn:concat(get-property('operation', 'jobCodesString'),get-property('jobCodeObject'),',')"
                                             scope="operation" />
                                          <property name="jobCodeIndex" expression="get-property('operation','jobCodeIndex') + 1"
                                             scope="operation" />
                                       </sequence>
                                    </target>
                                 </iterate>
                                 <filter
                                    xpath="get-property('operation', 'jobCodeCount')=get-property('operation', 'jobCodeIndex')">
                                    <then>
                                       <property name="jobCodesString"
                                          expression="fn:substring(get-property('operation','jobCodesString'), 1, fn:string-length(get-property('operation','jobCodesString'))-1)"
                                          scope="operation" />
                                       <property name="message"
                                          expression="fn:concat('{results:[',get-property('operation','jobCodesString'),']}')" />
                                       <property name="status" value="Success" />
                                       <call-template target="responseHandlerTemplate">
                                          <with-param name="id" value="{$ctx:id}" />
                                          <with-param name="activity" value="tsheets_addJobCodes" />
                                          <with-param name="status" value="{$ctx:status}" />
                                          <with-param name="message" value="{$ctx:message}" />
                                       </call-template>
                                    </then>
                                 </filter>
                              </then>
                              <else>
                                 <property name="status" value="Error" />
                                 <property name="message" expression="json-eval($.)" />
                                 <call-template target="responseHandlerTemplate">
                                    <with-param name="id" value="{$ctx:id}" />
                                    <with-param name="activity" value="tsheets_addJobCodes" />
                                    <with-param name="status" value="{$ctx:status}" />
                                    <with-param name="message" value="{$ctx:message}" />
                                 </call-template>
                              </else>
                           </filter>
                           <loopback />
                        </then>
                     </filter>
                  </else>
               </filter>
            </then>
            <else>
               <property name="id" value="{}" />
               <property name="status" value="Skipped" />
               <property name="message" expression="json-eval($.)" />
               <call-template target="responseHandlerTemplate">
                  <with-param name="id" value="{$ctx:id}" />
                  <with-param name="activity" value="basecrm_retrieveWonDeals" />
                  <with-param name="status" value="{$ctx:status}" />
                  <with-param name="message" value="{$ctx:message}" />
               </call-template>
               <loopback />
            </else>
         </filter>
      </inSequence>
      <outSequence>
         <payloadFactory media-type="json">
            <format>
               {
                  "Response":{
                     "process":"FreeAgent-retrieveWonDealsAndCreateProjectsAndJobCodes",
                     "activityResponse":[$1]
                  }
               }
            </format>
            <args>
               <arg expression="get-property('operation','responseString')" />
            </args>
         </payloadFactory>
         <property name="messageType" value="application/json" scope="axis2" />
         <send />
      </outSequence>
   </target>
   <description />
</proxy>                                                                                                   


Sample request for retrieving won deals from Base CRM and creating new projects with a new contacts in FreeAgent and adding job codes in TSheets
{
   "baseCrmApiUrl": "https://sales.futuresimple.com",
   "baseCrmEmail":"sampath.liyanage@myport.ac.uk",
   "baseCrmPassword":"1qaz2wsx@",
   "freeAgentApiUrl":"https://api.sandbox.freeagent.com",
   "freeAgentAccessToken":"1EAfIRnsNqVyncU9UXcdJwnCpweOeLfX-YDteF0fk",
   "tSheetsApiUrl":"https://rest.tsheets.com",
   "tSheetsAccessToken":"S.1__1424fbd6f71dc7ce0bdd89268d2d9726efe7e31c"
}