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/.

Deal Management in PipelineDeals

The second use case in the PipelineDeals business scenario is deal management. This page describes the relevant tasks and the operations you use in the PipelineDeals connector and the other ESB connectors. It contains the following sections:

Overview

The flow for deal management is illustrated in the following diagram. The ESB connectors for Google Calendar, Wunderlist and Dropbox will be used to connect to each service.

Creating calendar entries, calendar events and creating tasks

  1. Retrieve deal details from the PipelineDeals API using the getDeal operation.
  2. Create a new calendar entry in the PipelineDeals API using the createCalendarEntry operation,
  3. If the calendar entry type is equal to 'CalendarEvent':
    1. Retrieve user from the PipelineDeals API using the getUser operation.
    2. Retrieve company details from the PipelineDeals API using the getCompany operation.
    3. Retrieve the deal owner's e-mail address from the PipelineDeals API using the getUser operation.
    4. Create and share a calendar event in the Google Calendar API for the given calendar ID using the createEvent operation.

  4. If the calendar entry type is equal to 'CalendarTask':
    1. Create a new list in the Wunderlist API using the createList operation.
    2. Update the PipelineDeals company custom field with the Wunderlist list ID using the updateCompany operation.
    3. Update the custom field of the deal in the PipelineDeals API with the Wunderlist list ID using the updateDeal operation.
    4. Check if the folder exists for the company in the Wunderlist API using the listFolders operation.
    5. Create a new folder for the company in the Wunderlist API using the createFolder operation.
    6. Update the company folder with the list ID using the updateFolder operation in the Wunderlist API.
    7. Using the addMember operation add the user to the list in the Wunderlist API.
    8. Create a new task in the Wunderlist API using the createTask operation.
    9. Create a note for the task with the PipelineDeals calendar entry ID in the Wunderlist API using the createNote operation.
    10. Create a reminder for the task in the Wunderlist API using the createReminder operation if there is  due date in the calendar entry. 

    Note

    Assume that the company’s Google Calendar is shared among its customers and lists in Wunderlist are created manually.

Wunderlist operations
PipelineDeals operations
Google Calendar operations
Samples
Sample Template for creating calendar events in Google Calendar for the given Calendar ID
<?xml version="1.0" encoding="UTF-8"?>
<!--
   Copyright (c) 2005-2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
   WSO2 Inc. licenses this file to you under the Apache License,
   Version 2.0 (the "License"); you may not use this file except
   in compliance with the License.
   You may obtain a copy of the License at
   http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   KIND, either express or implied. See the License for the
   specific language governing permissions and limitations
   under the License.
-->
<!-- This template responsible for creating calendar event in Google Calendar 
	for the given Calendar ID -->
<template xmlns="http://ws.apache.org/ns/synapse" name="createCalendarEvents">
    <!-- Google Calendar related template parameters -->
    <parameter name="apiUrl" description="API url of Google Calendar." />
    <parameter name="accessToken" description="The access token to authorize the requests to Google Calendar." />
    <parameter name="calendarId" description="ID of the Google Calendar." />
    <parameter name="description" description="Descrition of the event." />
    <parameter name="summary" description="Summary of the event." />
    <parameter name="start" description="Start time of the event." />
    <parameter name="end" description="End time of the event." />
    <parameter name="attendeeEmail" description="Email of the event attendee." />
    <parameter name="common.id" description="ID object to create an event." />
	
    <sequence>
	
        <!-- Google Calendar related template properties -->
        <property name="apiUrl" expression="$func:apiUrl" />
        <property name="accessToken" expression="$func:accessToken" />
        <property name="calendarId" expression="$func:calendarId" />
        <property name="description" expression="$func:description" />
        <property name="summary" expression="$func:summary" />
        <property name="start" expression="$func:start" />
        <property name="end" expression="$func:end" />
        <property name="attendeeEmail" expression="$func:attendeeEmail" />
        <property name="common.id" expression="$func:common.id" />
        <property name="googlecalendar.attendees" expression="fn:concat('[{&quot;email&quot;:&quot;',get-property('attendeeEmail'),'&quot;}]')" />
        
		<googlecalendar.init>
            <apiUrl>{$ctx:apiUrl}</apiUrl>
            <accessToken>{$ctx:accessToken}</accessToken>
        </googlecalendar.init>
        <googlecalendar.createEvent>
            <calendarId>{$ctx:calendarId}</calendarId>
            <description>{$ctx:description}</description>
            <summary>{$ctx:summary}</summary>
            <start>{$ctx:start}</start>
            <end>{$ctx:end}</end>
            <attendees>{$ctx:googlecalendar.attendees}</attendees>
        </googlecalendar.createEvent>
		
        <property name="googleCalendar.eventId" expression="json-eval($.id)" />
		
        <filter source="boolean(get-property('googleCalendar.eventId'))" regex="false">
            <then>
                <property name="common.id" expression="get-property('common.id')" />
                <property name="status" value="Error" />
                <property name="message" expression="json-eval($)" />
                <call-template target="responseHandlerTemplate">
                    <with-param name="id" value="{$ctx:common.id}" />
                    <with-param name="activity" value="googleCalendar_createEvent" />
                    <with-param name="status" value="{$ctx:status}" />
                    <with-param name="message" value="{$ctx:message}" />
                </call-template>
            </then>
            <else>
                <property name="common.id" expression="fn:concat('googleCalendar_eventId:',get-property('googleCalendar.eventId'), ',', get-property('common.id'))" />
                <property name="status" value="Success" />
                <property name="message" value="Calendar event has been created." />
                <call-template target="responseHandlerTemplate">
                    <with-param name="id" value="{$ctx:common.id}" />
                    <with-param name="activity" value="googleCalendar_createEvent" />
                    <with-param name="status" value="{$ctx:status}" />
                    <with-param name="message" value="{$ctx:message}" />
                </call-template>
            </else>
        </filter>
    </sequence>
</template>
Sample Proxy for creating a calendar entry for a deal in PipeLineDeals API and then creating calendar events in the Google Calendar API if the type is equal to 'CalendarEntry' or creating task in the Wunderlist API if the type is equal to 'CalendarTask'
<?xml version="1.0" encoding="UTF-8"?>
<!--
   Copyright (c) 2005-2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
   WSO2 Inc. licenses this file to you under the Apache License,
   Version 2.0 (the "License"); you may not use this file except
   in compliance with the License.
   You may obtain a copy of the License at
   http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   KIND, either express or implied. See the License for the
   specific language governing permissions and limitations
   under the License.
-->
<!-- Create a Calendar Entry for a Deal in PipeLineDeals API and then Create Calendar Event in Google Calendar API 
	 if the Type is equal to CalendarEntry. Create Task in Wunderlist API if the Type is equal to CalendarTask. -->
<proxy xmlns="http://ws.apache.org/ns/synapse" name="pipelinedeals_createCalendarEventAndTasks" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
   <target>
      <inSequence onError="faultHandlerSeq">
	  
         <!--PipeLineDeals Properties -->
         <property name="pipeLineDeals.apiUrl" value="https://api.pipelinedeals.com" />
         <property name="pipeLineDeals.apiKey" expression="json-eval($.pipeLineDeals.apiKey)" />
         <property name="pipeLineDeals.calendarEntry" expression="json-eval($.pipeLineDeals.calendarEntry)" />
         <!-- GoogleCalendar Properties -->
         <property name="googleCalendar.apiUrl" value="https://www.googleapis.com" />
         <property name="googleCalendar.accessToken" expression="json-eval($.googleCalendar.accessToken)" />
         <property name="googleCalendar.calendarId" expression="json-eval($.googleCalendar.calendarId)" />
         <!-- Wunderlist Properties -->
         <property name="wunderlist.apiUrl" value="https://a.wunderlist.com" />
         <property name="wunderlist.accessToken" expression="json-eval($.wunderlist.accessToken)" />
         <property name="wunderlist.clientId" expression="json-eval($.wunderlist.clientId)" />
         <property name="wunderlist.remindOnDaysBefore" expression="json-eval($.wunderlist.remindOnDaysBefore)" />
		 
         <!--Process only if the calendar entries are available -->
         <filter source="boolean(get-property('pipeLineDeals.calendarEntry'))" regex="false">
            <then>
               <property name="id" value="{}" />
               <call-template target="responseHandlerTemplate">
                  <with-param name="id" value="{$ctx:id}" />
                  <with-param name="activity" value="pipelinedeals_createCalendarEntry" />
                  <with-param name="status" value="Skipped" />
                  <with-param name="message" value="No calendar entry details to process." />
               </call-template>
            </then>
            <else>
               <property name="pipeLineDeals.calendarEntryType" expression="json-eval($.pipeLineDeals.calendarEntry.type)" />
               <property name="pipeLineDeals.calendarEntryDueDate" expression="json-eval($.pipeLineDeals.calendarEntry.dueDate)" />
               <property name="pipeLineDeals.calendarEntryName" expression="json-eval($.pipeLineDeals.calendarEntry.name)" />
               <property name="pipeLineDeals.startTime" expression="json-eval($.pipeLineDeals.calendarEntry.startTime)" />
               <property name="pipeLineDeals.endTime" expression="json-eval($.pipeLineDeals.calendarEntry.endTime)" />
               <property name="pipeLineDeals.calendarEntryDescription" expression="json-eval($.pipeLineDeals.calendarEntry.description)" />
               <property name="pipeLineDeals.calendarEntryAssociationId" expression="json-eval($.pipeLineDeals.calendarEntry.dealId)" />
               <filter source="boolean(get-property('pipeLineDeals.calendarEntryAssociationId'))" regex="false">
                  <then>
                     <property name="id" value="{}" />
                     <property name="status" value="Skipped" />
                     <property name="message" value="Deal ID is required." />
                     <call-template target="responseHandlerTemplate">
                        <with-param name="id" value="{$ctx:id}" />
                        <with-param name="activity" value="pipelinedeals_createCalendarEntry" />
                        <with-param name="status" value="{$ctx:status}" />
                        <with-param name="message" value="{$ctx:message}" />
                     </call-template>
                     <loopback />
                  </then>
                  <else>
                     <pipelinedeals.init>
                        <apiUrl>{$ctx:pipeLineDeals.apiUrl}</apiUrl>
                        <apiKey>{$ctx:pipeLineDeals.apiKey}</apiKey>
                     </pipelinedeals.init>
                     <pipelinedeals.getDeal>
                        <dealId>{$ctx:pipeLineDeals.calendarEntryAssociationId}</dealId>
                     </pipelinedeals.getDeal>
					 
                     <property name="pipelinedeals.dealId" expression="json-eval($.id)" />
                     <property name="pipeLineDeals.deal.customFields" expression="json-eval($.custom_fields)" />
                     <property name="pipelinedeals.deal.ownerId" expression="json-eval($.user.id)" />
                     <property name="pipeLineDeals.calendarEntryCompanyId" expression="json-eval($.company_id)" />
                     <property name="wunderlist.deal.name" expression="json-eval($.name)" />
                     
					 <filter source="boolean(get-property('pipelinedeals.dealId'))" regex="false">
                        <then>
                           <property name="id" value="{}" />
                           <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="pipelinedeals_createCalendarEntry" />
                              <with-param name="status" value="{$ctx:status}" />
                              <with-param name="message" value="{$ctx:message}" />
                           </call-template>
                           <loopback />
                        </then>
                        <else>
                           <header name="Content-Encoding" action="remove" scope="transport" />
                           <!-- Calling PipeLineDeals createCalendarEntry method to create a
                              new calendar entry -->
                           <pipelinedeals.init>
                              <apiUrl>{$ctx:pipeLineDeals.apiUrl}</apiUrl>
                              <apiKey>{$ctx:pipeLineDeals.apiKey}</apiKey>
                           </pipelinedeals.init>
                           <pipelinedeals.createCalendarEntry>
                              <type>{$ctx:pipeLineDeals.calendarEntryType}</type>
                              <dueDate>{$ctx:pipeLineDeals.calendarEntryDueDate}</dueDate>
                              <name>{$ctx:pipeLineDeals.calendarEntryName}</name>
                              <companyId>{$ctx:pipeLineDeals.calendarEntryCompanyId}</companyId>
                              <startTime>{$ctx:pipeLineDeals.startTime}</startTime>
                              <endTime>{$ctx:pipeLineDeals.endTime}</endTime>
                              <description>{$ctx:pipeLineDeals.calendarEntryDescription}</description>
                              <associationType>Deal</associationType>
                              <associationId>{$ctx:pipeLineDeals.calendarEntryAssociationId}</associationId>
                           </pipelinedeals.createCalendarEntry>
						   
                           <property name="pipeLineDeals.calendarEntryId" expression="json-eval($.id)" />
                           <filter source="boolean(get-property('pipeLineDeals.calendarEntryId'))" regex="false">
                              <then>
                                 <property name="id" value="{}" />
                                 <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="pipelinedeals_createCalendarEntry" />
                                    <with-param name="status" value="{$ctx:status}" />
                                    <with-param name="message" value="{$ctx:message}" />
                                 </call-template>
                              </then>
                              <else>
                                 <property name="id" expression="fn:concat('calendarEntryId:',get-property('pipeLineDeals.calendarEntryId'))" />
                                 <property name="status" value="Success" />
                                 <property name="message" value="Calendar entry has been created." />
                                 <call-template target="responseHandlerTemplate">
                                    <with-param name="id" value="{$ctx:id}" />
                                    <with-param name="activity" value="pipelinedeals_createCalendarEntry" />
                                    <with-param name="status" value="{$ctx:status}" />
                                    <with-param name="message" value="{$ctx:message}" />
                                 </call-template>
								 
                                 <filter xpath="get-property('pipeLineDeals.calendarEntryType') = 'CalendarEvent'">
                                    <then>
                                       <property name="pipeLineDeals.calendarEntry.startTime" expression="json-eval($.start_time)" />
                                       <property name="pipeLineDeals.calendarEntry.endTime" expression="json-eval($.end_time)" />
                                       <property name="googleCalendar.eventSummary" expression="get-property('pipeLineDeals.calendarEntryName')" />
                                       <property name="googleCalendar.eventDescription" expression="get-property('pipeLineDeals.calendarEntryDescription')" />
                                       <script language="js">
										   <![CDATA[
												 var startTime=mc.getProperty('pipeLineDeals.calendarEntry.startTime');
												 var endTime=mc.getProperty('pipeLineDeals.calendarEntry.endTime');
												 var dateTimeArray;
												 var date="";
												 var time="";
												 var timeZone="";
												 var dateTime="";
												 if(startTime!=null && startTime!=""){
													dateTimeArray=startTime.split(" ");
												   date=dateTimeArray[0];
												   date = date.replace("/", "-");
												   time=dateTimeArray[1];
												   timeZone=dateTimeArray[2];
												   timeZone=timeZone.substring(0, 3)+":"+timeZone.substring(3, 5);
												   dateTime=date+"T"+time+timeZone;
												   mc.setProperty("googleCalendar.startTime", dateTime);
												}
												if(endTime!=null && endTime!=""){
												   dateTimeArray=endTime.split(" ");
												   date=dateTimeArray[0];
												   date = date.replace("/", "-");
												   time=dateTimeArray[1];
												   timeZone=dateTimeArray[2];
												   timeZone=timeZone.substring(0, 3)+":"+timeZone.substring(3, 5);
												   dateTime=date+"T"+time+timeZone;
												   mc.setProperty("googleCalendar.endTime", dateTime);
												}
											]]>
										</script>
                                       <payloadFactory media-type="json">
                                          <format>
											{
                                                "start": {
                                                   "dateTime": "$1"
                                                },
                                                "end": {
                                                   "dateTime": "$2"
                                                }
                                             }
										  </format>
                                          <args>
                                             <arg expression="get-property('googleCalendar.startTime')" />
                                             <arg expression="get-property('googleCalendar.endTime')" />
                                          </args>
                                       </payloadFactory>
                                       <property name="googleCalendar.eventStart" expression="json-eval($.start)" />
                                       <property name="googleCalendar.eventEnd" expression="json-eval($.end)" />
                                       
									   <!-- Calling manageEvents sequence to do the events related operations -->
                                       <sequence key="manageEvents" />
                                    </then>
                                    <else>
                                        <!-- Calling manageTasks sequence to do the task related operations -->
										<log><property name="pipeLineDeals.deal.customFields-Inside Proxy" expression="get-property('pipeLineDeals.deal.customFields')" /></log>
									    <sequence key="manageTasks" />
                                    </else>
                                 </filter>
                              </else>
                           </filter>
						   
                        </else>
                     </filter>
					 
                  </else>
               </filter>
            </else>
         </filter>
         <loopback />
      </inSequence>
	  
      <outSequence>
         <payloadFactory media-type="json">
            <format>{
               "Response":{
               "process":"pipelinedeals-createCalendarEventAndTasks",
               "activityResponse":[$1]
               }
               }</format>
            <args>
               <arg expression="get-property('operation','responseString')" />
            </args>
         </payloadFactory>
         <property name="messageType" value="application/json" scope="axis2" />
         <send />
      </outSequence>
   </target>
</proxy>
Sample Request for creating a calendar entry for a deal in PipeLineDeals API and then creating calendar events in the Google Calendar API if the type is equal to 'CalendarEntry' or creating task in the Wunderlist API if the type is equal to 'CalendarTask'
{
	"pipeLineDeals":{
		"apiKey":"Jng6CgUAfIHnYe0k8",
		"calendarEntry":{
				"name":"Calendar entry 1",
				"description":"Desc for the enrty",
				"type":"CalendarEvent",
				"startTime":"2015-06-28 08:00:00",
				"endTime":"2015-06-30 11:47:15",
				"dueDate":"2016-01-08",
				"dealId":"8463484"
		}
	},
	"googleCalendar":{
		"accessToken":"ya29.oAEjSvp93P2XSxQK4-1n0BZFvCIcDT-3b6D1Ks3VlK8aU8YW32zKNRVwLkz6w2aFrkfOhw1_wnFQ",
		"calendarId":"myport.ac.uk_nmfirgk057c94vihesfcva48@group.calendar.google.com"
	},
	"wunderlist":{
		"accessToken":"de4149ee73eb7d00a945fe39bec2a0ef54d4f765dcbb695643e08faaeab",
		"clientId":"89c0107602b6b51ce94",
		"remindOnDaysBefore":"1"
	}
}

Note

 The following are the parameter descriptions:

  • pipeLineDeals.calendarEntry: JSON object which contains the following attributes to create a calendar entry in the PipelineDeals API:
    • name: The name of the calendar entry.
    • description: Description of the calendar entry.
    • type: Type of the calendar entry (possible values are 'CalendarEvent' and 'CalendarTask').
    • startTime: Start time of the calendar entry only if the calendar entry type is 'CalendarEvent' (e.g.: 2015-06-28 08:00:00).
    • endTime: End time of the calendar entry only if the calendar entry type is 'CalendarEvent' (e.g.: 2015-06-30 11:47:15).
    • dueDate: Due date of the calendar entry only if the calendar entry type is 'CalendarTask' (e.g.: 2016-01-08).
    • dealId: PipelineDeals ID to create a calendar entry ID.
  • googleCalendar.calendarId: Google calendar ID to create calendar events.
  • wunderlist.remindOnDaysBefore: Number of days to remind before the task due date.

Deals used in the scenario must have a person associated with it.

Retrieving completed tasks and updating tasks

  1. Retrieve all deals in the 'Active' stage from the PipelineDeals API using the listDeals operation.
  2. Retrieve all the completed tasks for the selected list from the Wunderlist API using the listTasks operation.
  3. Retrieve the related PipelineDeals calendar entry ID from the completed tasks using the listNotes operation in the Wunderlist API.
  4. Update the calendar entry as completed in the PipelineDeals API using the updateCalendarEntry operation.
  5. If the calendar entry has been updated, delete the task from the Wunderlist API using the deleteTask operation.
Wunderlist operations
PipelineDeals operations
Samples
Sample Proxy for retrieving Wunderlist completed tasks for the PipelineDeals deals in the stage of 'Active'. Updating the associated tasks in PipelineDeals as 'completed'
<?xml version="1.0" encoding="UTF-8"?>
<!--
   Copyright (c) 2005-2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
   WSO2 Inc. licenses this file to you under the Apache License,
   Version 2.0 (the "License"); you may not use this file except
   in compliance with the License.
   You may obtain a copy of the License at
   http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   KIND, either express or implied.  See the License for the
   specific language governing permissions and limitations
   under the License.
-->
<!--For the active deals in PipelineDeals, retrieve completed tasks from wunderlist and update them back in PipelineDeals-->
<proxy xmlns="http://ws.apache.org/ns/synapse" name="pipelinedeals_retrieveCompletedTasksAndUpdateCalendarEntries" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
    <target>
        <inSequence>
            
			<!-- wunderList Properties -->
            <property name="uri.var.wunderlist.apiUrl" value="https://a.wunderlist.com" />
            <property name="uri.var.wunderlist.accessToken" expression="json-eval($.wunderlist.accessToken)" />
            <property name="uri.var.wunderlist.clientId" expression="json-eval($.wunderlist.clientId)" />
            
			<!-- pipelineDeals Properties -->
            <property name="uri.var.pipelinedeals.apiUrl" value="http://api.pipelinedeals.com" />
            <property name="uri.var.pipelinedeals.apiKey" expression="json-eval($.pipelinedeals.apiKey)" />
            
			<!-- Common properties -->
            <property name="id.empty" value="{}" />
            <property name="responseString" value="" scope="operation" />
            <property name="activityName" value="pipelinedeals_retrievePotentialsAndCreateDeals" scope="operation" />
            
			<!-- Calling retrieveDealsAndUpdateTasks-verifyPrerequisites sequence to get deal stages and wunderList list Id-->
            <sequence key="retrieveCompletedTasksAndUpdateCalendarEntries-verifyPrerequisites" />
            
			<!---Remove unnecessary headers-->
            <sequence key="removeResponseHeaders" />
            
			<!-- Call pipelinedeals connector listDeals method to list all deals in a given stage 'open' -->
            <pipelinedeals.init>
                <apiUrl>{$ctx:uri.var.pipelinedeals.apiUrl}</apiUrl>
                <apiKey>{$ctx:uri.var.pipelinedeals.apiKey}</apiKey>
            </pipelinedeals.init>
            <pipelinedeals.listDeals>
                <dealStage>{$ctx:pipelinedeals.dealStageId}</dealStage>
            </pipelinedeals.listDeals>
            <property name="deal.count" expression="count(//entries)" scope="operation" />
            <property name="deal.entries" expression="json-eval($.entries)" />
            
			<!-- START: Proceed to update deals only if there are active deals. -->
            <filter source="get-property('operation','deal.count')" regex="0.0">
                <then>
                    <property name="id" value="{}" />
                    <property name="status" value="Skipped" />
                    <property name="message" value="No deals to process." />
                    <call-template target="responseHandlerTemplate">
                        <with-param name="id" value="{$ctx:id}" />
                        <with-param name="activity" value="pipelinedeals_updateTasks" />
                        <with-param name="status" value="{$ctx:status}" />
                        <with-param name="message" value="{$ctx:message}" />
                    </call-template>
                    <loopback />
                </then>
                <else>
                    <!---Remove unnecessary headers-->
                    <sequence key="removeResponseHeaders" />
                    <property name="dealIndex" value="0" scope="operation" />
                    <property name="taskIndex" value="0" scope="operation" />
                    <property name="taskCount" value="0" scope="operation" />
            
					<!--FOR EACH task : BEGIN-->
                    <iterate continueParent="false" id="deals" expression="//entries" sequential="true">
                        <target>
                            <sequence>
                                <property name="uri.var.pipelinedeals.dealId" expression="json-eval($.entries.id)" />
                                <property name="pipelinedeals.dealCustomFields" expression="json-eval($.entries.custom_fields)" />
                    
								<!--To get the custom field value which stores the wunderlist list Id in pipeline deals -->
                                <script language="js">
									<![CDATA[
										var dealCustomFields = eval("(" + mc.getProperty('pipelinedeals.dealCustomFields') + ")");
										var wunderlistCustomField = mc.getProperty('pipelinedeals.customFieldString');
								
										if(dealCustomFields.hasOwnProperty(wunderlistCustomField)) {
											var wunderlistId = ""+dealCustomFields[wunderlistCustomField];
											mc.setProperty("uri.var.pipelinedeals.wunderlistId",wunderlistId);
										}
									]]>
								</script>
                               
							   <!-- START: Proceed to retrieve tasks only if the related wunderList list ID is given for the deal. -->
                                <filter source="boolean(get-property('uri.var.pipelinedeals.wunderlistId'))" regex="false">
                                    <then>
                                        <property name="id" expression="fn:concat('pipelinedeals_dealId:',get-property('uri.var.pipelinedeals.dealId'))" />
                                        <property name="status" value="Error" />
                                        <property name="message" value="wunderList Id is not given in the custom field" />
                                        <call-template target="responseHandlerTemplate">
                                            <with-param name="id" value="{$ctx:id}" />
                                            <with-param name="activity" value="wunderlist_getCompletedTasks" />
                                            <with-param name="status" value="{$ctx:status}" />
                                            <with-param name="message" value="{$ctx:message}" />
                                        </call-template>
                                        <property name="dealIndex" expression="get-property('operation','dealIndex') + 1" scope="operation" />
                                    </then>
                                    <else>
                                        <!-- Call wunderlist connector listTasks method to list all the completed tasks for the selected list -->
                                        <wunderlist.init>
                                            <apiUrl>{$ctx:uri.var.wunderlist.apiUrl}</apiUrl>
                                            <clientId>{$ctx:uri.var.wunderlist.clientId}</clientId>
                                            <accessToken>{$ctx:uri.var.wunderlist.accessToken}</accessToken>
                                        </wunderlist.init>
                                        <wunderlist.listTasks>
                                            <listId>{$ctx:uri.var.pipelinedeals.wunderlistId}</listId>
                                            <completed>true</completed>
                                        </wunderlist.listTasks>
                                        <property name="tCount" expression="count(//jsonArray/jsonElement)" />
										
                                        <property name="dealIndex" expression="get-property('operation','dealIndex') + 1" scope="operation" />
                                        
										<!-- START: Proceed updating calender events only if there are completed tasks. -->
                                        <filter xpath="get-property('tCount') != 0.0">
                                            <then>
                                                <property name="taskCount" expression="get-property('operation','taskCount') + get-property('tCount')" scope="operation" />
                                                <property name="tCountdd" expression="get-property('operation','taskCount')" />
                                                
												<!--FOR EACH task : BEGIN -->
                                                <iterate continueParent="false" id="tasks" expression="//jsonArray/jsonElement" sequential="true">
                                                    <target>
                                                        <sequence>
                                                            <property name="uri.var.wunderlist.taskId" expression="//jsonElement/id/text()" />
                                                            <property name="uri.var.wunderlist.taskRevision" expression="//jsonElement/revision/text()" />
                                                            <property name="uri.var.listId" action="remove" />
                                                           
														   <!-- Call wunderlist connector listNotes method to list all the notes belongs to a particular task -->
                                                            <wunderlist.init>
                                                                <apiUrl>{$ctx:uri.var.wunderlist.apiUrl}</apiUrl>
                                                                <clientId>{$ctx:uri.var.wunderlist.clientId}</clientId>
                                                                <accessToken>{$ctx:uri.var.wunderlist.accessToken}</accessToken>
                                                            </wunderlist.init>
                                                            <wunderlist.listNotes>
                                                                <taskId>{$ctx:uri.var.wunderlist.taskId}</taskId>
                                                            </wunderlist.listNotes>
                                                            <property name="wunderlist.note" expression="json-eval($.[0].content)" />
                                                            
															<script language="js">
																<![CDATA[
																	 var notes = ''+mc.getProperty('wunderlist.note');
																	 //Get the pipeline taskId from wunderlist task's notes
																	 if(new java.lang.String(notes).startsWith('PipelineDeals Calendar Entry ID')) {
																		 var taskId = notes.split(':')[1];
																		 mc.setProperty("uri.var.pipelinedeals.taskId",taskId);
																	 }
																]]>
															</script>
                                                            
															<!-- START: Proceed to retrieve tasks only if the related wunderList list ID is given for the deal. -->
                                                            <filter source="boolean(get-property('uri.var.pipelinedeals.taskId'))" regex="false">
                                                                <then>
                                                                    <property name="id" expression="fn:concat('wunderlist_taskId:',get-property('uri.var.wunderlist.taskId'))" />
                                                                    <property name="status" value="Skipped" />
                                                                    <property name="message" value="No task is associated with the wunderlist task." />
                                                                    <call-template target="responseHandlerTemplate">
                                                                        <with-param name="id" value="{$ctx:id}" />
                                                                        <with-param name="activity" value="wunderlist_getCompletedTasks" />
                                                                        <with-param name="status" value="{$ctx:status}" />
                                                                        <with-param name="message" value="{$ctx:message}" />
                                                                    </call-template>
                                                                </then>
                                                                <else>
                                                                    <!-- Call pipelinedeals connector updateCalendarEntry method to update the calender entry as completed -->
                                                                    <pipelinedeals.init>
                                                                        <apiUrl>{$ctx:uri.var.pipelinedeals.apiUrl}</apiUrl>
                                                                        <apiKey>{$ctx:uri.var.pipelinedeals.apiKey}</apiKey>
                                                                    </pipelinedeals.init>
                                                                    <pipelinedeals.updateCalendarEntry>
                                                                        <complete>true</complete>
                                                                        <calendarEntryId>{$ctx:uri.var.pipelinedeals.taskId}</calendarEntryId>
                                                                    </pipelinedeals.updateCalendarEntry>
                                                                    <property name="pipelinedeals.updatedTaskId" expression="json-eval($.id)" />
                                                                    
																	<!-- START: Append the response message according to the updateCalendarEntry response -->
                                                                    <filter source="boolean(get-property('pipelinedeals.updatedTaskId'))" regex="false">
                                                                        <then>
                                                                            <property name="id" expression="fn:concat('wunderlist_taskId:',get-property('uri.var.wunderlist.taskId'),',pipelinedeals_taskId:',get-property('pipelinedeals.updatedTaskId'))" />
                                                                            <property name="status" value="Error" />
                                                                            <property name="message" expression="json-eval($)" />
                                                                        </then>
                                                                        <else>
                                                                            <property name="id" expression="fn:concat('wunderlist_taskId:',get-property('uri.var.wunderlist.taskId'),',pipelinedeals_taskId:',get-property('pipelinedeals.updatedTaskId'))" />
                                                                            <property name="status" value="Success" />
                                                                            <property name="message" value="Task has been updated." />
                                                                        </else>
                                                                    </filter>
                                                                    <!--Call the responseHandler template-->
                                                                    <call-template target="responseHandlerTemplate">
                                                                        <with-param name="activity" value="pipelinedeals_updateCalenderEntry" />
                                                                        <with-param name="id" value="{$ctx:id}" />
                                                                        <with-param name="status" value="{$ctx:status}" />
                                                                        <with-param name="message" value="{$ctx:message}" />
                                                                    </call-template>
                                                                    
																	<!-- START: Proceed with deleting the wunderlist task only if the calender entry has been updated-->
                                                                    <filter source="boolean(get-property('pipelinedeals.updatedTaskId'))" regex="true">
                                                                        <then>
                                                                            <!-- Call wunderlist connector deleteTask method to delete the completed task -->
                                                                            <wunderlist.init>
                                                                                <apiUrl>{$ctx:uri.var.wunderlist.apiUrl}</apiUrl>
                                                                                <clientId>{$ctx:uri.var.wunderlist.clientId}</clientId>
                                                                                <accessToken>{$ctx:uri.var.wunderlist.accessToken}</accessToken>
                                                                            </wunderlist.init>
                                                                            <wunderlist.deleteTask>
                                                                                <taskId>{$ctx:uri.var.wunderlist.taskId}</taskId>
                                                                                <revision>{$ctx:uri.var.wunderlist.taskRevision}</revision>
                                                                            </wunderlist.deleteTask>
                                                                           
																		   <!--This dummy call is made because of the delete operation returns content-length '0' -->
                                                                            <wunderlist.init>
                                                                                <apiUrl>{$ctx:uri.var.wunderlist.apiUrl}</apiUrl>
                                                                                <clientId>{$ctx:uri.var.wunderlist.clientId}</clientId>
                                                                                <accessToken>{$ctx:uri.var.wunderlist.accessToken}</accessToken>
                                                                            </wunderlist.init>
                                                                            <wunderlist.listNotes>
                                                                                <taskId>{$ctx:uri.var.wunderlist.taskId}</taskId>
                                                                            </wunderlist.listNotes>
                                                                        </then>
                                                                    </filter>
                                                                    <!-- END: Proceed with deleting the wunderlist task only if the calender entry has been updated-->
                                                                </else>
                                                            </filter>
                                                            <!-- END: Proceed to retrieve tasks only if the related wunderList list ID is given for the deal. -->
                                                            <property name="taskIndex" expression="get-property('operation','taskIndex') + 1" scope="operation" />
                                                        </sequence>
                                                    </target>
                                                </iterate>
                                                <!--FOR EACH task : END -->
                                            </then>
                                        </filter>
                                        <!-- END: Proceed updating calender events only if there are completed tasks. -->
                                    </else>
                                </filter>
                                <!-- END: Proceed to retrieve tasks only if the related wunderList list ID is given for the deal. -->
                                <filter xpath="(get-property('operation','dealIndex') = get-property('operation', 'deal.count')) and  (get-property('operation','taskIndex') = get-property('operation','taskCount'))">
                                    <then>
										<!-- Append a message to send to the user if no deals were created. -->
										<filter xpath="get-property('operation','taskCount') = 0.0">
											<then>
												<call-template target="responseHandlerTemplate">
													<with-param name="activity" value="wunderlist_getCompletedTasks" />
													<with-param name="id" value="{$ctx:id.empty}" />
													<with-param name="status" value="Skipped" />
													<with-param name="message" value="None of the deals in 'Active' stage have completed tasks." />
												</call-template>
											</then>
										</filter>
                                        <loopback />
                                    </then>
                                </filter>
                            </sequence>
                        </target>
                    </iterate>
                    <!--FOR EACH task end : END-->
                </else>
            </filter>
        </inSequence>
        <outSequence>
            <!-- Send the constructed response to the user. -->
            <payloadFactory media-type="json">
                <format>{
               "Response":{
				  "process":"pipelinedeals_retrieveDealsAndUpdateTasks",
                  "activityResponse": [$1]
               }
            }</format>
                <args>
                    <arg expression="get-property('operation', 'responseString')" />
                </args>
            </payloadFactory>
            <send />
        </outSequence>
    </target>
</proxy>
Sample Request for retrieving Wunderlist completed tasks for the PipelineDeals deals in the stage of 'Active'. Updating the associated tasks in PipelineDeals as 'completed'
{
    "pipelinedeals": {
        "apiKey": "Jng6CgAfIWHnYe0k8"
    },
    "wunderlist": {
        "accessToken": "de4149ee73eb7d00a945fe39bec2a0ef54d4f765dcbb695643e08faaeab",
        "clientId":"89c0107602bb51ce94"
    }
}

Deal documentation

  1. Retrieve documents from the given folder using the getMetadata operation in the Dropbox API.

  2. Retrieve deal information from the PipelineDeals API using the getDeal operation.
  3. Move the document to another Dropbox folder to avoid creating duplicated documents using the move operation in the Dropbox API.
  4. Create a public direct link for the file in the Dropbox API using the createDirectLink operation.
  5. Create the document in the PipelineDeals API using the createDocument operation.
  6. Retrieve the information of the deal owner from the PipelineDeals API using the getUser operation.
  7. Retrieve account information from the PipelineDeals API using the getAccountDetails operation.
  8. Send the survey to the deal owner through the Mandrill API using the sendMessage operation.
Dropbox operations
PipelineDeals operations
Mandrill operations
Samples
Sample Proxy for iterating over the files created in a temporary folder in Dropbox and moving the files to a permanent folder in the Dropbox account, creating them as documents in PipelineDeals under the deal the files are associated with, sending an e-mail to the owner of the deal, notifying that a new document has been created for the Deal in PipelineDeals
<?xml version="1.0" encoding="UTF-8"?>
<!--
   Copyright (c) 2005-2015, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
   WSO2 Inc. licenses this file to you under the Apache License,
   Version 2.0 (the "License"); you may not use this file except
   in compliance with the License.
   You may obtain a copy of the License at
   http://www.apache.org/licenses/LICENSE-2.0
   Unless required by applicable law or agreed to in writing,
   software distributed under the License is distributed on an
   "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   KIND, either express or implied.  See the License for the
   specific language governing permissions and limitations
   under the License.
-->
<!-- The proxy will retrieve the documents found in a temporary folder in Dropbox and move them to a permanent folder (under a folder created for the associated deal).
	 It will also create those documents in PipelineDeals and notify the owner of the deal regarding the document.-->
<proxy xmlns="http://ws.apache.org/ns/synapse" name="pipelinedeals_synchronizeDocuments" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
    <target>
        <inSequence>
            <!-- Dropbox Properties -->
            <property name="dropbox.apiUrl" value="https://api.dropbox.com" />
            <property name="dropbox.accessToken" expression="json-eval($.dropbox.accessToken)" />
            <property name="dropbox.newFilesPath" expression="json-eval($.dropbox.newFilesPath)" />
            <property name="dropbox.permanentDealFilesPath" expression="json-eval($.dropbox.permanentDealFilesPath)" />
			
            <!-- PipelineDeals Properties -->
            <property name="pipelinedeals.apiUrl" value="https://api.pipelinedeals.com" />
            <property name="pipelinedeals.apiKey" expression="json-eval($.pipelinedeals.apiKey)" />
			
            <!-- Madnrill Properties -->
            <property name="mandrill.apiUrl" value="https://mandrillapp.com" />
            <property name="mandrill.apiKey" expression="json-eval($.mandrill.apiKey)" />
			
			<!-- Common Properties -->
            <property name="id.empty" value="{}" />
            <property name="responseString" value="" scope="operation" />
			
            <!-- Get all the files from the 'New Files' Folder. This folder would be used as a temp folder to add new deal related files. -->
            <dropbox.init>
                <apiUrl>{$ctx:dropbox.apiUrl}</apiUrl>
                <root>auto</root>
                <path>{$ctx:dropbox.newFilesPath}</path>
                <accessToken>{$ctx:dropbox.accessToken}</accessToken>
            </dropbox.init>
            <dropbox.getMetadata>
                <list>true</list>
            </dropbox.getMetadata>
            <sequence key="removeResponseHeaders" />
			
			<!-- Decode binary response to a JSON object. -->
            <sequence key="base64DecodeDropboxResponse" />
			
            <property name="dropbox.status" expression="$axis2:HTTP_SC" />
            <!-- Terminate the scenario for a negative response. -->
            <filter xpath="get-property('dropbox.status') != 200">
                <then>
                    <property name="message" expression="json-eval($)" />
                    <call-template target="responseHandlerTemplate">
                        <with-param name="activity" value="dropbox_getNewDealFiles" />
                        <with-param name="id" value="{$ctx:id.empty}" />
                        <with-param name="status" value="Error" />
                        <with-param name="message" value="{$ctx:message}" />
                    </call-template>
                    <loopback />
                </then>
            </filter>
			
            <property name="fileCount" expression="count(//contents)" />
            <property name="fileIndex" expression="0" scope="operation" />
			
            <!-- START: Append a skip message to the user if there are no new files in dropbox. -->
            <filter source="get-property('fileCount')" regex="0.0">
                <then>
                    <call-template target="responseHandlerTemplate">
                        <with-param name="activity" value="dropbox_getNewDealFiles" />
                        <with-param name="id" value="{$ctx:id.empty}" />
                        <with-param name="status" value="Skipped" />
                        <with-param name="message" value="There aren't any new files to be processed." />
                    </call-template>
                    <loopback />
                </then>
                <else>
                    <!--FOR EACH File: BEGIN -->
                    <iterate continueParent="false" id="files" expression="//contents" sequential="true">
                        <target>
                            <sequence>
                                <property name="dropbox.oldFilePath" expression="//path/text()" />
								
                                <script language="js">
									<![CDATA[
										// Adding a delay due to the API reate limiting.
										java.lang.Thread.sleep(2000);
										
										var oldFilePath = mc.getProperty('dropbox.oldFilePath');
										var permanentDealFilesPath = mc.getProperty('dropbox.permanentDealFilesPath');
										
										var paths = oldFilePath.split('/');										
										var filename = paths[paths.length-1];
										
										if(filename.indexOf('-') != -1){
											// ID of the deal
											var dealId = filename.split('-')[0];
											mc.setProperty('pipelinedeals.dealId', dealId);	
											// Name of the file without ID								
											mc.setProperty('dropbox.filename', new java.lang.String(filename).substring(dealId.length()+1));
										}
									]]>
								</script>
								
                                <!-- START: Get the deal details if the deal ID could be retrieved. -->
                                <filter source="boolean(get-property('pipelinedeals.dealId'))" regex="true">
                                    <then>
                                        <!-- Retrieve deal information. -->
                                        <pipelinedeals.init>
                                            <apiUrl>{$ctx:pipelinedeals.apiUrl}</apiUrl>
                                            <apiKey>{$ctx:pipelinedeals.apiKey}</apiKey>
                                        </pipelinedeals.init>
                                        <pipelinedeals.getDeal>
                                            <dealId>{$ctx:pipelinedeals.dealId}</dealId>
                                        </pipelinedeals.getDeal>
                                        <sequence key="removeResponseHeaders" />
										
                                        <property name="pipelinedeals.dealId" expression="json-eval($.id)" />
                                        <property name="pipelinedeals.dealName" expression="json-eval($.name)" />
                                        <property name="pipelinedeals.contactId" expression="json-eval($.primary_contact_id)" />
                                        <property name="pipelinedeals.ownerId" expression="json-eval($.user.id)" />
                                        <property name="pipelinedeals.dealSummary" expression="json-eval($.summary)" />
										
                                        <!-- START: Proceed only if the deal information could be successfully retrieved. -->
                                        <filter source="boolean(get-property('pipelinedeals.dealId'))" regex="true">
                                            <then>
                                                <property name="dropbox.newFilePath" expression="fn:concat(get-property('dropbox.permanentDealFilesPath'), '/', get-property('pipelinedeals.dealName'), '/', get-property('dropbox.filename'))" />
                                                <!-- Move the file to the deal folder. -->
                                                <dropbox.init>
                                                    <apiUrl>{$ctx:dropbox.apiUrl}</apiUrl>
                                                    <accessToken>{$ctx:dropbox.accessToken}</accessToken>
                                                    <root>auto</root>
                                                </dropbox.init>
                                                <dropbox.move>
                                                    <fromPath>{$ctx:dropbox.oldFilePath}</fromPath>
                                                    <toPath>{$ctx:dropbox.newFilePath}</toPath>
                                                </dropbox.move>
                                                <sequence key="removeResponseHeaders" />
												
												<!-- Decode binary response to a JSON object. -->
                                                <sequence key="base64DecodeDropboxResponse" />
												
                                                <property name="dropbox.path" expression="json-eval($.path)" />
												
                                                <!-- START: Proceed only if the file was successfully moved to permanent storage. -->
                                                <filter xpath="get-property('dropbox.path') != get-property('dropbox.newFilePath')">
                                                    <then>
                                                        <property name="id" expression="fn:concat('dropbox_fileName:', get-property('dropbox.filename'))" />
                                                        <property name="message" expression="json-eval($)" />
                                                        <call-template target="responseHandlerTemplate">
                                                            <with-param name="activity" value="dropbox_moveFile" />
                                                            <with-param name="id" value="{$ctx:id}" />
                                                            <with-param name="status" value="Error" />
                                                            <with-param name="message" value="{$ctx:message}" />
                                                        </call-template>
                                                    </then>
                                                    <else>
                                                        <!-- Create a public direct link for the file. -->
                                                        <dropbox.init>
                                                            <apiUrl>{$ctx:dropbox.apiUrl}</apiUrl>
                                                            <accessToken>{$ctx:dropbox.accessToken}</accessToken>
                                                            <root>auto</root>
                                                            <path>{$ctx:dropbox.path}</path>
                                                        </dropbox.init>
                                                        <dropbox.createDirectLink />
                                                        <sequence key="removeResponseHeaders" />
														
														<!-- Decode binary response to a JSON object. -->
                                                        <sequence key="base64DecodeDropboxResponse" />
														
                                                        <property name="dropbox.directUrl" expression="json-eval($.url)" />
                                                        <property name="dropbox.expires" expression="json-eval($.expires)" />
														
                                                        <!-- START: Proceed to create the document only if the direct link is created successfully. -->
                                                        <filter source="boolean(get-property('dropbox.directUrl'))" regex="false">
                                                            <then>
                                                                <property name="id" expression="fn:concat('dropbox_fileName:', get-property('dropbox.filename'))" />
                                                                <property name="message" expression="json-eval($)" />
                                                                <call-template target="responseHandlerTemplate">
                                                                    <with-param name="activity" value="dropbox_createDirectLink" />
                                                                    <with-param name="id" value="{$ctx:id}" />
                                                                    <with-param name="status" value="Error" />
                                                                    <with-param name="message" value="{$ctx:message}" />
                                                                </call-template>
                                                            </then>
                                                            <else>
                                                                <!-- Create the document in PipelineDeals. -->
                                                                <pipelinedeals.init>
                                                                    <apiUrl>{$ctx:pipelinedeals.apiUrl}</apiUrl>
                                                                    <apiKey>{$ctx:pipelinedeals.apiKey}</apiKey>
                                                                    <attributes>{$ctx:pipelinedeals.attributes}</attributes>
                                                                </pipelinedeals.init>
                                                                <pipelinedeals.createDocument>
                                                                    <title>{$ctx:dropbox.filename}</title>
                                                                    <dealId>{$ctx:pipelinedeals.dealId}</dealId>
                                                                    <personId>{$ctx:pipelinedeals.contactId}</personId>
                                                                    <ownerId>{$ctx:pipelinedeals.ownerId}</ownerId>
                                                                    <publicFileUrl>{$ctx:dropbox.directUrl}</publicFileUrl>
                                                                </pipelinedeals.createDocument>
                                                                <sequence key="removeResponseHeaders" />
																
                                                                <property name="pipelinedeals.fileId" expression="json-eval($.id)" />
																
                                                                <!-- START: Proceed only if the document was created successfully. -->
                                                                <filter source="boolean(get-property('pipelinedeals.fileId'))" regex="false">
                                                                    <then>
                                                                        <property name="id" expression="fn:concat('pipelinesdeals_dealId:', get-property('pipelinedeals.dealId'), ',dropbox_fileName:', get-property('dropbox.filename'))" />
                                                                        <property name="message" expression="json-eval($)" />
                                                                        <call-template target="responseHandlerTemplate">
                                                                            <with-param name="activity" value="pipelinedeals_createDocument" />
                                                                            <with-param name="id" value="{$ctx:id}" />
                                                                            <with-param name="status" value="Skipped" />
                                                                            <with-param name="message" value="{$ctx:message}" />
                                                                        </call-template>
                                                                    </then>
                                                                    <else>
                                                                        <property name="id" expression="fn:concat('pipelinesdeals_dealId:', get-property('pipelinedeals.dealId'), ',dropbox_fileName:', get-property('dropbox.filename'), ',pipelinesdeals_documentId:', get-property('pipelinedeals.fileId'))" />
                                                                        <call-template target="responseHandlerTemplate">
                                                                            <with-param name="activity" value="pipelinedeals_createDocument" />
                                                                            <with-param name="id" value="{$ctx:id}" />
                                                                            <with-param name="status" value="Success" />
                                                                            <with-param name="message" value="Document has been successfully created." />
                                                                        </call-template>
																		
                                                                        <!-- Get deal owner information. -->
                                                                        <pipelinedeals.init>
                                                                            <apiUrl>{$ctx:pipelinedeals.apiUrl}</apiUrl>
                                                                            <apiKey>{$ctx:pipelinedeals.apiKey}</apiKey>
                                                                        </pipelinedeals.init>
                                                                        <pipelinedeals.getUser>
                                                                            <userId>{$ctx:pipelinedeals.ownerId}</userId>
                                                                        </pipelinedeals.getUser>
                                                                        <sequence key="removeResponseHeaders" />
																		
                                                                        <property name="pipelinedeals.userEmail" expression="json-eval($.email)" />
                                                                        <property name="pipelinedeals.userFirstName" expression="json-eval($.first_name)" />
																		
                                                                        <!-- Get account information. -->
                                                                        <pipelinedeals.init>
                                                                            <apiUrl>{$ctx:pipelinedeals.apiUrl}</apiUrl>
                                                                            <apiKey>{$ctx:pipelinedeals.apiKey}</apiKey>
                                                                        </pipelinedeals.init>
                                                                        <pipelinedeals.getAccountDetails />
                                                                        <sequence key="removeResponseHeaders" />
																		
                                                                        <property name="pipelinedeals.users" expression="json-eval($.users)" />
                                                                        <script language="js">
																			<![CDATA[
																				var users = eval("(" + mc.getProperty('pipelinedeals.users') + ")");								  
																				for(var i=0; i<users.length; i++){
																					if(users[i].is_account_admin == true){
																						mc.setProperty('mandrill.fromName', users[i].first_name);
																						mc.setProperty('mandrill.fromEmail', users[i].email);
																						break;
																					}
																				}
																													  
																				var userEmail = mc.getProperty('pipelinedeals.userEmail');							  
																				var userFirstName = mc.getProperty('pipelinedeals.userFirstName');		
																				var fileName = mc.getProperty('dropbox.filename');										  
																				var filePath = mc.getProperty('dropbox.path');													  
																				var filePublicLink = mc.getProperty('dropbox.directUrl');								  
																				var fileExpiration = mc.getProperty('dropbox.expires');									  
																				var dealName = mc.getProperty('pipelinedeals.dealName');							  
																				var dealSummary = mc.getProperty('pipelinedeals.dealSummary');	
																				var dealSummaryText = '';
																				if(dealSummary != null && dealSummary != ''){
																					var dealSummaryText = '<p>Summary: <i>' + dealSummary + '</i></p>';
																				}																				
																				
																				var mailHTMLUser = '<h3>Dear ' + userFirstName + ',</h3><p>A new document has been created for the Deal.</p><p>Deal Name: <b>' + dealName + '</b></p>' + dealSummaryText + '<p>Document Name: <b>' + fileName + '</b></p><p>Dropbox Path: <b>' + filePath + "</b></p><p>`</p><p>You can also view/download the file by <u><a href='" + filePublicLink + "'>Clicking here</a></u>. (Link expires on " + fileExpiration + ')</p> <p>`</p><p> </p>`<p> </p>`<p> </p><p>This is an auto-generated email. Please do not reply.</p>';
																				mc.setProperty('mandrill.htmlUser', mailHTMLUser);	
																																		
																				mc.setProperty('mandrill.subject', 'New Document added for the Deal [' + dealName + ']');
																				
																				var mailToUser = '[{"email": "' + userEmail + '", "name": "' + userFirstName + '", "type": "to"}]';
																				mc.setProperty('mandrill.toUser', mailToUser);
																			]]>
																		</script>
																		
                                                                        <property name="mandrill.htmlUser" expression="fn:concat('&lt;html&gt;', get-property('mandrill.htmlUser'), '&lt;/html&gt;')" />
                                                                        
																		<!-- Send survey to deal owner. -->
                                                                        <mandrill.init>
                                                                            <apiKey>{$ctx:mandrill.apiKey}</apiKey>
                                                                            <apiUrl>{$ctx:mandrill.apiUrl}</apiUrl>
                                                                            <format>json</format>
                                                                        </mandrill.init>
                                                                        <mandrill.sendMessage>
                                                                            <html>{$ctx:mandrill.htmlUser}</html>
                                                                            <subject>{$ctx:mandrill.subject}</subject>
                                                                            <fromEmail>{$ctx:mandrill.fromEmail}</fromEmail>
                                                                            <fromName>{$ctx:mandrill.fromName}</fromName>
                                                                            <to>{$ctx:mandrill.toUser}</to>
                                                                        </mandrill.sendMessage>
                                                                        <sequence key="removeResponseHeaders" />
																		
                                                                        <property name="mandrill.mailIdUser" expression="json-eval($[0]._id)" />
                                                                        <property name="id" expression="fn:concat('pipelinedeals_documentId:', get-property('pipelinedeals.fileId'), ',pipelinedeals_userId:', get-property('pipelinedeals.ownerId'))" />
                                                                        
																		<!-- START: Append a message to be sent to the user regarding the status of the send email operation. -->
                                                                        <filter source="boolean(get-property('mandrill.mailIdUser'))" regex="true">
                                                                            <then>
                                                                                <property name="status" value="Success" />
                                                                                <property name="message" value="A notification email has been sent to the owner of the deal." />
                                                                            </then>
                                                                            <else>
                                                                                <property name="status" value="Error" />
                                                                                <property name="message" expression="json-eval($)" />
                                                                            </else>
                                                                        </filter>
                                                                        <!-- END: Append a message to be sent to the user regarding the status of the send email operation. -->
                                                                        
																		<call-template target="responseHandlerTemplate">
                                                                            <with-param name="activity" value="mandrill_sendNotificationToOwner" />
                                                                            <with-param name="id" value="{$ctx:id}" />
                                                                            <with-param name="status" value="{$ctx:status}" />
                                                                            <with-param name="message" value="{$ctx:message}" />
                                                                        </call-template>
                                                                    </else>
                                                                </filter>
                                                                <!-- END: Proceed only if the document was created successfully. -->
                                                            </else>
                                                        </filter>
                                                        <!-- END: Proceed to create the document only if the direct link is created successfully. -->
                                                    </else>
                                                </filter>
                                                <!-- END: Proceed only if the deal has an associated folder created in Box. -->
                                            </then>
                                            <else>
                                                <property name="id" expression="fn:concat('dropbox_fileName:', get-property('dropbox.filename'))" />
                                                <call-template target="responseHandlerTemplate">
                                                    <with-param name="activity" value="pipelinedeals_getAssociatedDeal" />
                                                    <with-param name="id" value="{$ctx:id}" />
                                                    <with-param name="status" value="Skipped" />
                                                    <with-param name="message" value="File is associated with an invalid deal or the deal has been deleted." />
                                                </call-template>
                                            </else>
                                        </filter>
                                        <!-- END: Proceed only if the deal information could be successfully retrieved. -->
                                    </then>
                                    <else>
                                        <property name="id" expression="fn:concat('dropbox_filePath:', get-property('dropbox.oldFilePath'))" />
                                        <call-template target="responseHandlerTemplate">
                                            <with-param name="activity" value="pipelinedeals_getAssociatedDeal" />
                                            <with-param name="id" value="{$ctx:id}" />
                                            <with-param name="status" value="Skipped" />
                                            <with-param name="message" value="File doesn't have a deal associated with it." />
                                        </call-template>
                                    </else>
                                </filter>
                                <!-- END: Get the deal details if the deal ID could be retrieved. -->
								
                                <!--Increment the file count by 1 -->
                                <property name="fileIndex" expression="get-property('operation','fileIndex') + 1" scope="operation" />
								
                                <!-- Loopback after last iteration. -->
                                <filter xpath="get-property('fileCount') = get-property('operation', 'fileIndex')">
                                    <then>
                                        <loopback />
                                    </then>
                                </filter>
								
                            </sequence>
                        </target>
                    </iterate>
                    <!--FOR EACH File: END -->
                </else>
            </filter>
            <!-- END: Append a skip message to the user if there are no new files in dropbox. -->
        </inSequence>
        <outSequence>
            <!-- Send the constructed response to the user. -->
            <payloadFactory media-type="json">
                <format>
					{
					   "Response":{
						   "process":"pipelinedeals_synchronizeDocuments",
						   "activityResponse": [$1]
					   }
					}
				</format>
                <args>
                    <arg expression="get-property('operation', 'responseString')" />
                </args>
            </payloadFactory>
            <send />
        </outSequence>
    </target>
</proxy>
Sample Request for iterating over the files created in a temporary folder in Dropbox and moving the files to a permanent folder in the Dropbox account, creating them as documents in PipelineDeals under the deal the files are associated with, sending an e-mail to the owner of the deal, notifying that a new document has been created for the Deal in PipelineDeals
{
	"dropbox":{
		"accessToken": "XcUIVw-rY2AAAAAAAAAjuF8om7SDOhGwtwucoxMYzVds5-Lv0dPkM2hL-wb9F",
		"newFilesPath": "/PipelineDeals/New Files",
		"permanentDealFilesPath": "/PipelineDeals/Deal Files"
	},
	"pipelinedeals":{
		"apiKey": "Jng6CgUAfHnYe0k8"
	},
	"mandrill":{
		"apiKey": "d6jyblpJ1GeoJLZ5_12g"
	}
}

Note

 The following are the parameter descriptions:

  • dropbox.newFilesPath: The path of the temporary folder in Dropbox inside which the new files will be uploaded.
  • dropbox.permanentDealFilesPath: The path of the permanent folder in Dropbox into which the files would be be moved for permanent storage.

Special Notes

  • New files uploaded to the temporary folder in Dropbox should be named according to the following format: <PipelineDeals Deal ID>-<File name>.<extension>
    Each file should be associated to an existing deal in PipelineDeals. This is done by prepending the deal ID to the file name separated by a hyphen.

  • Execution time of the scenario would be fairly longer since a timeout has been added in the scenario to overcome rate limiting issue.