The fourth use case in the ZohoCRM business scenario is managing support cases. This page describes the related tasks and the operations you use in the ZohoCRM connector and the other ESB connectors.
Overview
The flow for managing support cases is illustrated in the following diagram. The ESB connectors for ZohoCRM and JIRA will be used to connect to each service.
Create a case for feedback received for products in ZohoCRM using the insertRecords operation.
Retrieve the case details from ZohoCRM using the getRecordsById operation and t rack the case as an issue in JIRA using the createIssue operation.
- When a particular issue is "Done" in JIRA, retrieve its latest comment using the searchJira operation and update the details in the relevant case in ZohoCRM using the updateRecords operation.
ZohoCRM operations
JIRA operations
Samples
"jiraQuery" will extract the issues from the given time frame.
"issueCaseIdMap" will map the issues in JIRA.
<!-- This template creates a case in ZohoCRM and then creates a corresponding issue in JIRA using the details retrieved from the created case in ZohoCRM --> <template name="zohocrm-createAndRetrieveCase" xmlns="http://ws.apache.org/ns/synapse"> <!-- Zoho CRM parameters --> <property name="zohoApiUrl" description="The ZohoCRM API URL" /> <property name="zohoAccessToken" description="Encrypted alphanumeric string to authenticate the ZohoCRM credentials" /> <property name="zohoScope" description="ZohoCRM scope. Specify the value as crmapi" /> <property name="zohoNewFormat" description="The newFormat, an integer determine whether null values should be excluded(1) or included(2)" /> <property name="zohoVersion" description="Columns selected" /> <property name="zohoXmlData" description="The xml string containing the data to be inserted" /> <property name="zohoWfTrigger" description="The wfTrigger parameter is used to trigger the workflow rule while inserting record into CRM account" /> <property name="zohoDuplicateCheck" description="Checking the duplicate records and throw an error response" /> <sequence> <!-- zoho CRM properties --> <property name="uri.var.zohoApiUrl" expression="json-eval($.zohoApiUrl)"/> <property name="uri.var.zohoAccessToken" expression="json-eval($.zohoAccessToken)"/> <property name="uri.var.zohoScope" expression="json-eval($.zohoScope)"/> <property name="uri.var.zohoNewFormat" expression="json-eval($.zohoNewFormat)"/> <property name="uri.var.zohoVersion" expression="json-eval($.zohoVersion)"/> <property name="uri.var.zohoXmlData" expression="json-eval($.zohoXmlData)"/> <property name="uri.var.zohoWfTrigger" expression="json-eval($.zohoWfTrigger)"/> <property name="uri.var.zohoDuplicateCheck" expression="json-eval($.zohoDuplicateCheck)"/> <!-- isApproval property was set to false so the case will immediately add to the account and can proceed with other API calls, otherwise manual approving should be needed--> <property name="uri.var.zohoIsApproval" value="false"/> <property name="uri.var.zohoModuleType" value="Cases"/> <!-- zoho CRM create Case--> <zohocrm.init> <apiUrl>{$ctx:uri.var.zohoApiUrl}</apiUrl> <accessToken>{$ctx:uri.var.zohoAccessToken}</accessToken> <scope>{$ctx:uri.var.zohoScope}</scope> </zohocrm.init> <zohocrm.insertRecords> <newFormat>{$ctx:uri.var.zohoNewFormat}</newFormat> <version>{$ctx:uri.var.zohoVersion}</version> <xmlData>{$ctx:uri.var.zohoXmlData}</xmlData> <wfTrigger>{$ctx:uri.var.zohoWfTrigger}</wfTrigger> <duplicateCheck>{$ctx:uri.var.zohoDuplicateCheck}</duplicateCheck> <isApproval>{$ctx:uri.var.zohoIsApproval}</isApproval> <moduleType>{$ctx:uri.var.zohoModuleType}</moduleType> </zohocrm.insertRecords> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_createCase" /> | ) * </call-template> <!-- Retrieving created case ID --> <property name="uri.var.caseId" expression="json-eval($.response.result.recorddetail.FL[0].content)"/> <!-- Check the availability of caseID to proceed with other API calls --> <filter source="boolean(get-property('uri.var.caseId'))" regex="false"> <loopback/> </filter> <header name="Expires" scope="transport" action="remove" /> <header name="Content-Type" scope="transport" action="remove" /> <header name="Date" scope="transport" action="remove" /> <header name="Server" scope="transport" action="remove" /> <header name="Transfer-Encoding" scope="transport" action="remove" /> <header name="Connection" scope="transport" action="remove" /> <header name="Vary" scope="transport" action="remove" /> <header name="Content-Encoding" scope="transport" action="remove" /> <!-- zoho CRM retrieve created Case--> <zohocrm.init> <apiUrl>{$ctx:uri.var.zohoApiUrl}</apiUrl> <accessToken>{$ctx:uri.var.zohoAccessToken}</accessToken> <scope>{$ctx:uri.var.zohoScope}</scope> </zohocrm.init> <zohocrm.getRecordsById> <id>{$ctx:uri.var.caseId}</id> <newFormat>{$ctx:uri.var.zohoNewFormat}</newFormat> <version>{$ctx:uri.var.zohoVersion}</version> <moduleType>{$ctx:uri.var.zohoModuleType}</moduleType> </zohocrm.getRecordsById> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_getCaseById" />| ) * </call-template> <!-- Retrieving case details --> <property name="uri.var.caseDetails" expression="json-eval($.response.result.Cases.row.FL)"/> <!-- Check the availability of caseDetails to proceed with other API calls --> <filter source="boolean(get-property('uri.var.caseDetails'))" regex="false"> <loopback/> </filter> </sequence> </template>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="zohocrm_jira_createCase" transports="https" statistics="disable" trace="disable" startOnLoad="true"> <target> <inSequence onError="faultHandlerSeq"> <!-- Zoho CRM API call related properties --> <property name="zohoApiUrl" expression="json-eval($.zohoApiUrl)"/> <property name="zohoAccessToken" expression="json-eval($.zohoAccessToken)"/> <property name="zohoScope" expression="json-eval($.zohoScope)"/> <property name="zohoNewFormat" expression="json-eval($.zohoNewFormat)"/> <property name="zohoVersion" expression="json-eval($.zohoVersion)"/> <property name="zohoXmlData" expression="json-eval($.zohoXmlData)"/> <property name="zohoWfTrigger" expression="json-eval($.zohoWfTrigger)"/> <property name="zohoDuplicateCheck" expression="json-eval($.zohoDuplicateCheck)"/> <!-- Jira API call related properties --> <property name="jiraAccountUrl" expression="json-eval($.jiraAccountUrl)"/> <property name="jiraUsername" expression="json-eval($.jiraUsername)"/> <property name="jiraPassword" expression="json-eval($.jiraPassword)"/> <property name="jiraProjectKey" expression="json-eval($.jiraProjectKey)"/> <property name="jiraSummary" expression="json-eval($.jiraSummary)"/> <property name="jiraIssueType" expression="json-eval($.jiraIssueType)"/> <call-template target="zohocrm-createAndRetrieveCase"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="zohoApiUrl" value="{$ctx:zohoApiUrl}" /> | <with-param name="zohoAccessToken" value="{$ctx:zohoAccessToken}" /> | <with-param name="zohoScope" value="{$ctx:zohoScope}" /> | <with-param name="zohoNewFormat" value="{$ctx:zohoNewFormat}" /> | <with-param name="zohoVersion" value="{$ctx:zohoVersion}" /> | <with-param name="zohoXmlData" value="{$ctx:zohoXmlData}" /> | <with-param name="zohoWfTrigger" value="{$ctx:zohoWfTrigger}" /> | <with-param name="zohoDuplicateCheck" value="{$ctx:zohoDuplicateCheck}" /> | ) * </call-template> <script language="js"> var jsn = eval("(" + mc.getProperty("uri.var.caseDetails") + ")"); for (var i = 0; i < jsn.length ; i++) { // If the description is present uses it for JIRA Issue creation if(jsn[i].val == "Description"){ mc.setProperty('uri.var.jiraDescription', jsn[i].content); } } // Empty the description if it was not retrieved from ZohoCRM (will be assigned string null from mc.setProperty()) if(mc.getProperty('uri.var.jiraDescription') == 'null'){ mc.setProperty('uri.var.jiraDescription', ''); } </script> <header name="Expires" scope="transport" action="remove" /> <header name="Content-Type" scope="transport" action="remove" /> <header name="Date" scope="transport" action="remove" /> <header name="Server" scope="transport" action="remove" /> <header name="Transfer-Encoding" scope="transport" action="remove" /> <header name="Connection" scope="transport" action="remove" /> <header name="Vary" scope="transport" action="remove" /> <header name="Content-Encoding" scope="transport" action="remove" /> <!-- Jira create Issue--> <jira.init> <uri>{$ctx:jiraAccountUrl}</uri> <username>{$ctx:jiraUsername}</username> <password>{$ctx:jiraPassword}</password> </jira.init> <jira.createIssue> <projectKey>{$ctx:jiraProjectKey}</projectKey> <summary>{$ctx:jiraSummary}</summary> <description>{$ctx:uri.var.jiraDescription}</description> <issueType>{$ctx:jiraIssueType}</issueType> </jira.createIssue> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="jira_createIssue" /> | ) * </call-template> <loopback/> </inSequence> <outSequence> <property name="messageType" value="application/json" scope="axis2" /> <!-- Generate the chained response of all the API calls in createLeads --> <payloadFactory media-type="json"> <format> { "Response":[$1] } </format> <args> <arg expression="get-property('uri.var.responseString')" /> </args> </payloadFactory> <send/> </outSequence> </target> <description/> </proxy>
{ "zohoApiUrl": "https://crm.zoho.com", "zohoAccessToken": "0c255a80ed272cb8a57e4f688f89741f", "zohoScope": "crmapi", "zohoNewFormat": 2, "zohoVersion": 2, "zohoXmlData": "<Cases><row no=\"1\"><FL val=\"Subject\">ERR</FL></row></Cases>", "zohoWfTrigger": true, "zohoDuplicateCheck": "2", "jiraAccountUrl":"http://cd-pdissanayake:8080", "jiraUsername":"admin", "jiraPassword":"1qaz2wsx@", "jiraProjectKey":"SI", "jiraSummary":"issueOnPrabodhaPCSummary", "jiraIssueType":"New Feature" }
<!-- This template updates an issue in JIRA by adding a comment and then creates the same comment in corresponding case inside ZohoCRM case --> <template name="zohocrm-updateIssue" xmlns="http://ws.apache.org/ns/synapse"> <!-- Zoho CRM parameters --> <parameter name="zohoApiUrl" description="The Zoho api URL" /> <parameter name="zohoAccessToken" description="Encrypted alphanumeric string to authenticate the Zoho credentials" /> <parameter name="zohoScope" description="Zoho CRM scope, Specify the value as crmapi" /> <parameter name="zohoNewFormat" description="The newFormat, an integer determine whether null values should be excluded(1) or included(2)" /> <parameter name="zohoVersion" description="Columns selected" /> <parameter name="zohoWfTrigger" description="The wfTrigger parameter is used to trigger the workflow rule while inserting record into CRM account" /> <parameter name="zohoCaseId" description="Zoho Case ID, to add the comment. This should be the corresponding case of the JIRA issue." /> <parameter name="comment" description="Comment to be updated in ZohoCRM Case" /> <sequence> <!-- zoho CRM properties --> <property name="uri.var.zohoApiUrl" expression="$func:zohoApiUrl"/> <property name="uri.var.zohoAccessToken" expression="$func:zohoAccessToken"/> <property name="uri.var.zohoScope" expression="$func:zohoScope"/> <property name="uri.var.zohoNewFormat" expression="$func:zohoNewFormat"/> <property name="uri.var.zohoVersion" expression="$func:zohoVersion"/> <property name="uri.var.zohoWfTrigger" expression="$func:zohoWfTrigger"/> <property name="uri.var.zohoCaseId" expression="$func:zohoCaseId"/> <property name="uri.var.zohoModuleType" value="Cases"/> <property name="uri.var.comment" expression="$func:comment"/> <script language="js"> <![CDATA[ var comment = mc.getProperty("uri.var.comment"); var xmlData = '<Cases> <row no=\"1\"> <FL val=\"Internal Comments\">' + comment + '</FL> </row> </Cases>'; mc.setProperty('uri.var.zohoXmlData', xmlData); ]]> </script> <!-- zoho CRM insert comment to Case --> <zohocrm.init> <apiUrl>{$ctx:uri.var.zohoApiUrl}</apiUrl> <accessToken>{$ctx:uri.var.zohoAccessToken}</accessToken> <scope>{$ctx:uri.var.zohoScope}</scope> </zohocrm.init> <zohocrm.updateRecords> <newFormat>{$ctx:uri.var.zohoNewFormat}</newFormat> <version>{$ctx:uri.var.zohoVersion}</version> <id>{$ctx:uri.var.zohoCaseId}</id> <xmlData>{$ctx:uri.var.zohoXmlData}</xmlData> <wfTrigger>{$ctx:uri.var.zohoWfTrigger}</wfTrigger> <moduleType>{$ctx:uri.var.zohoModuleType}</moduleType> </zohocrm.updateRecords> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_insertCommentForCase" /> | ) * </call-template> </sequence> </template>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="zohocrm_jira_followupIssues" transports="https" statistics="disable" trace="disable" startOnLoad="true"> <target> <inSequence onError="faultHandlerSeq"> <!-- Jira API call related properties --> <property name="jiraAccountUrl" expression="json-eval($.jiraAccountUrl)"/> <property name="jiraUsername" expression="json-eval($.jiraUsername)"/> <property name="jiraPassword" expression="json-eval($.jiraPassword)"/> <property name="jiraQuery" expression="json-eval($.jiraQuery)"/> <property name="jiraMaxResult" expression="json-eval($.jiraMaxResult)"/> <property name="jiraStartFrom" expression="json-eval($.jiraStartFrom)"/> <property name="jiraFields" value="comment"/> <!-- Zoho CRM API call related properties --> <property name="zohoApiUrl" expression="json-eval($.zohoApiUrl)"/> <property name="zohoAccessToken" expression="json-eval($.zohoAccessToken)"/> <property name="zohoScope" expression="json-eval($.zohoScope)"/> <property name="zohoNewFormat" expression="json-eval($.zohoNewFormat)"/> <property name="zohoVersion" expression="json-eval($.zohoVersion)"/> <property name="zohoWfTrigger" expression="json-eval($.zohoWfTrigger)"/> <property name="issueCaseIdMap" expression="json-eval($.issueCaseIdMap)"/> <property name="uri.var.responseBuilder" value="" scope="operation" /> <property name="uri.var.index" value="0" scope="operation" /> <!-- Jira Retrieve all issues --> <jira.init> <uri>{$ctx:jiraAccountUrl}</uri> <username>{$ctx:jiraUsername}</username> <password>{$ctx:jiraPassword}</password> </jira.init> <jira.searchJira> <query>{$ctx:jiraQuery}</query> <maxResult>{$ctx:jiraMaxResult}</maxResult> <startFrom>{$ctx:jiraStartFrom}</startFrom> <fields>{$ctx:jiraFields}</fields> </jira.searchJira> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="jira_searchIssues" /> | ) * </call-template> <property name="uri.var.getIssuesResponseString" expression="get-property('uri.var.responseString')" scope="operation" /> <property name="messageType" value="application/xml" scope="axis2" /> <property name="uri.var.issuesCount" expression="count(//issues)" scope="operation" /> <filter xpath="0 = get-property('operation', 'uri.var.issuesCount')"> <then> <payloadFactory media-type="json"> <format> { "activity":"zohocrm_retrieveIssuesFailure", "activityResponse":"No issues were found according to the provided JQL" } </format> </payloadFactory> <call-template target="responseHandlerTemplate"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="activityName" value="zohocrm_getIssuesFailure" /> | ) * </call-template> <property name="uri.var.responseBuilder" expression="json-eval($)" scope="operation" /> <loopback /> </then> </filter> <!-- Clears the rsponseString to avoid it being appended multiple times --> <property name="uri.var.responseString" value="" /> <iterate id="leadsIterator" expression="//issues" sequential="true" continueParent="true" preservePayload="true"> <target> <sequence> <property name="uri.var.jiraIssueKey" expression="(//*/key)[1]/text()" /> <property name="uri.var.comment" expression="(//*/comments/body)[last()]/text()"/> <script language="js"> var jiraIssueId = mc.getProperty('uri.var.jiraIssueKey'); var issueCaseIdMap = eval("("+mc.getProperty('issueCaseIdMap')+")"); var zohoCaseId = issueCaseIdMap[jiraIssueId]; mc.setProperty('uri.var.zohoCaseId', zohoCaseId); </script> <call-template target="zohocrm-updateIssue"> <!-- parameter values will be passed on to a sequence template --> ( <with-param name="zohoApiUrl" value="{$ctx:zohoApiUrl}" /> | <with-param name="zohoAccessToken" value="{$ctx:zohoAccessToken}" /> | <with-param name="zohoScope" value="{$ctx:zohoScope}" /> | <with-param name="zohoNewFormat" value="{$ctx:zohoNewFormat}" /> | <with-param name="zohoVersion" value="{$ctx:zohoVersion}" /> | <with-param name="zohoWfTrigger" value="{$ctx:zohoWfTrigger}" /> | <with-param name="zohoCaseId" value="{$ctx:uri.var.zohoCaseId}" /> | <with-param name="comment" value="{$ctx:uri.var.comment}" /> | ) * </call-template> <property name="uri.var.index" expression="get-property('operation','uri.var.index') + 1" scope="operation" /> <property name="uri.var.responseBuilder" expression="fn:concat(get-property('operation','uri.var.responseBuilder'), get-property('uri.var.responseString') , ', ')" scope="operation" /> </sequence> </target> </iterate> <filter xpath="get-property('operation', 'uri.var.index') = get-property('operation', 'uri.var.issuesCount')"> <then> <!-- Remove the final comma appended inside the iterator mediator for final response generation inside the outsequence --> <property name="uri.var.responseBuilder" expression="fn:substring(get-property('operation', 'uri.var.responseBuilder'), 0, fn:string-length(get-property('operation', 'uri.var.responseBuilder')))" scope="operation" /> <loopback /> </then> </filter> </inSequence> <outSequence> <property name="messageType" value="application/json" scope="axis2" /> <!-- Generate the chained response of all the API calls in createLeads --> <payloadFactory media-type="json"> <format> { "Response":[ $1, $2 ] } </format> <args> <arg expression="get-property('operation', 'uri.var.getIssuesResponseString')" /> <arg expression="get-property('operation', 'uri.var.responseBuilder')" /> </args> </payloadFactory> <send /> </outSequence> </target> <description /> </proxy>
{ "jiraAccountUrl":"http://cd-dvirajith:8080", "jiraUsername":"admin", "jiraPassword":"admin", "jiraQuery":"status%3D%22done%22%20AND%20updated%3EstartOfDay()", "jiraMaxResult":"30", "jiraStartFrom":"0", "issueCaseIdMap":{"TES-23":"1264711000000091001","TES-18":"1264711000000072003"}, "zohoApiUrl":"https://crm.zoho.com", "zohoAccessToken":"5fba482fb322c85b26783f68ee7900ae", "zohoScope":"crmapi", "zohoNewFormat":"1", "zohoVersion":"1", "zohoWfTrigger":false }