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

Customer Loyalty Management in Vend

 The third use case in the Vend business scenario is customer loyalty management. This page describes the relevant tasks and the operations you use in the Vend connector and the other ESB connectors. It contains the following sections:

Overview

The flow for customer loyalty management is illustrated in the following diagram. The ESB connectors for MailChimp, Nexmo and Beetrack will be used to connect to each service.


Updating subscribers' list and notifying customers

  1. Retrieve customers on a daily basis from the Vend API using the listCustomers operation.
  2. Notify customers about the change in loyalty balance using the sendMessage in the Nexmo API.
  3. Update the custom field of the customer in the Vend API using the updateCustomer operation.
  4. Retrieve the subscribers' list which matches the provided list name in the MailChimp API using the listSubscriberLists operation.
  5. Subscribe people to the list in the MailChimp API using the addSubscribersToList operation.
Vend operations
MailChimp operations
Nexmo operations

Note

  • Loyalty feature should be enabled in the Vend account for the case to be meaningful.
  • Only the customers who have their loyalty enabled will be considered for loyalty balance updates.

Samples
Sample Proxy for updating MailChimp subscribers’ lists with the customers in Vend and notifying customers in Vend regarding changes in their loyalty balance via SMS
<?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 list the customers from Vend and add them to Mailchimp subscribers' list if they're not already part of it.
   Furthermore it will notify the customers about their loyalty balance if it has changed. -->
<proxy xmlns="http://ws.apache.org/ns/synapse" name="vend_updateCustomerBaseAndNotifyLoyaltyBalance" transports="https,http" statistics="disable" trace="disable" startOnLoad="true">
   <target>
      <inSequence>
         <!-- Vend Properties -->
         <property name="vend.considerSince" expression="json-eval($.vend.considerSince)" />
         <property name="vend.fromName" expression="json-eval($.vend.fromName)" />
         <!-- ZohoCrm Properties -->
         <property name="mailchimp.apiUrl" expression="get-property('registry', 'connectors/Mailchimp/apiUrl')" />
         <property name="mailchimp.apiKey" expression="get-property('registry', 'connectors/Mailchimp/apiKey')" />
         <property name="mailchimp.listName" expression="json-eval($.mailchimp.listName)" />
         <!-- Nexmo Properties -->
         <property name="nexmo.apiUrl" expression="get-property('registry', 'connectors/Nexmo/apiUrl')" />
         <property name="nexmo.apiSecret" expression="get-property('registry', 'connectors/Nexmo/apiSecret')" />
         <property name="nexmo.apiKey" expression="get-property('registry', 'connectors/Nexmo/apiKey')" />
         <!-- Common properties -->
         <property name="id.empty" value="{}" />
         <property name="responseString" value="" scope="operation" />
         <!-- START: If the user has not provided the last modified date, keep a default of 7 previous days. -->
         <filter source="boolean(get-property('vend.considerSince'))" regex="false">
            <then>
               <script language="js">
                  <![CDATA[
                     // 604800000 - 7 days in milliseconds
                     mc.setProperty('vend.considerSince', new java.text.SimpleDateFormat('yyyy-MM-dd hh:mm:ss').format(new java.util.Date(new java.util.Date().getTime() - 604800000)));
                  ]]>
               </script>
            </then>
         </filter>
         <!-- END: If the user has not provided the last modified date, keep a default of 7 previous days. -->
         <!-- List all the people who were created/modified after the 'considerSince' date. -->
         <vend.init />
         <vend.listCustomers>
            <since>{$ctx:vend.considerSince}</since>
         </vend.listCustomers>
         <sequence key="removeResponseHeaders" />
         <property name="vend.apiUrl" expression="get-property('registry', 'connectors/Vend/apiUrl')" />
         <property name="vend.accessToken" expression="get-property('registry', 'connectors/Vend/accessToken')" />
         <property name="customerCount" expression="count(//customers)" />
         <!-- START: Proceed only if there are any customers to process. -->
         <filter xpath="get-property('customerCount') > 0.0">
            <then>
               <!--The script mediator will construct the array of subscribers to update. -->
               <script language="js">
                  <![CDATA[
                     // Construct the email array to add to the subscribers' list in Mailchimp.
                     var customers = mc.getPayloadJSON().customers;
                     var batchEmailString = '';    
                     
                     var noOfCustomers = customers.length;
                     if(noOfCustomers > 0){
                        for(var i=0; i<noOfCustomers; i++){
                           var email = customers[i].email;
                           if(email != null && email != ''){
                              batchEmailString = batchEmailString + '{ "email": { "email": "' + email + '" }, "email_type": "text" }';
                              if(i < noOfCustomers-1){
                                 batchEmailString = batchEmailString + ', ';
                              }
                           }
                        }
                        batchEmailString = '[' + batchEmailString + ']';
                     }
                     mc.setProperty('mailchimp.batchEmailString', batchEmailString);
                     
                     // Set the current date to a property for later use.
                     mc.setProperty('vend.currentDate', new java.text.SimpleDateFormat('yyyy-MM-dd').format(new java.util.Date()));
                  ]]>
               </script>
               <property name="customerIndex" expression="0" scope="operation" />
               <!--FOR EACH Customer: BEGIN -->
               <iterate continueParent="false" id="customers" expression="//customers" sequential="true">
                  <target>
                     <sequence>
                        <property name="vend.customerId" expression="//customers/id/text()" />
                        <property name="vend.customerLoyalityEnabled" expression="//customers/enable_loyalty/text()" />
                        <property name="vend.customerLoyalityBalance" expression="//customers/loyalty_balance/text()" />
                        <property name="vend.customerPreviousLoyality" expression="//customers/custom_field_1/text()" />
                        <property name="vend.customerMobile" expression="//customers/mobile/text()" />
                        <property name="vend.customerFirstName" expression="//customers/first_name/text()" />
                        <property name="vend.customerLastName" expression="//customers/last_name/text()" />
                        <property name="vend.customerName" expression="fn:concat(get-property('vend.customerFirstName'), ' ', get-property('vend.customerLastName'))" />
                        <!-- START: Proceed only if the customer has loyalty enabled. -->
                        <filter source="get-property('vend.customerLoyalityEnabled')" regex="1">
                           <then>
                              <!-- Verify whether the customer's loyalty balance has changed since last notification. -->
                              <script language="js">
                                 <![CDATA[
                                    var customerLoyalityBalance = mc.getProperty('vend.customerLoyalityBalance');
                                    var customerPreviousLoyality = mc.getProperty('vend.customerPreviousLoyality');
                                    var customerFirstName = mc.getProperty('vend.customerFirstName');
                                    var currentDate = mc.getProperty('vend.currentDate');
                                    var fromName = mc.getProperty('vend.fromName');                                          
                                    
                                    var proceed = 'false';
                                    
                                    if(customerPreviousLoyality == ''){
                                       if(customerLoyalityBalance > 0){
                                          proceed = 'true';
                                       }
                                    } else {
                                       if(!(new java.lang.Double(customerPreviousLoyality).equals(new java.lang.Double(customerLoyalityBalance)))){
                                          proceed = 'true';
                                       }
                                    }
                                    mc.setProperty('proceed', proceed);
                                    
                                    if(proceed == 'true'){
                                       var message = 'Hi ' + customerFirstName + ', Your loyalty balance as of ' + currentDate + ' is USD ' + new java.lang.Double(customerLoyalityBalance) + '! Please visit your nearest outlet to redeem the points. Thank you for shopping with us - ' + fromName + '.';
                                       mc.setProperty('nexmo.message', message);
                                    }
                                 ]]>
                              </script>
                              <!-- START: Proceed if there is a change in the loyalty balance of the customer. -->
                              <filter source="get-property('proceed')" regex="true">
                                 <then>
                                    <!-- Notify customer about the change in loyalty balance. -->
                                    <nexmo.init>
                                       <responseType>json</responseType>
                                       <apiUrl>{$ctx:nexmo.apiUrl}</apiUrl>
                                       <apiSecret>{$ctx:nexmo.apiSecret}</apiSecret>
                                       <apiKey>{$ctx:nexmo.apiKey}</apiKey>
                                    </nexmo.init>
                                    <nexmo.sendMessage>
                                       <to>{$ctx:vend.customerMobile}</to>
                                       <text>{$ctx:nexmo.message}</text>
                                       <from>{$ctx:vend.fromName}</from>
                                       <type>text</type>
                                    </nexmo.sendMessage>
                                    <sequence key="removeResponseHeaders" />
                                    <property name="sendMessage.errorMessage" expression="json-eval($.messages[0].error-text)" />
                                    <property name="id" expression="fn:concat('vend_customerId:', get-property('vend.customerId'))" />
                                    <!-- START: Proceed to update the custom field of the customer only if the SMS has been successfully sent. -->
                                    <filter source="boolean(get-property('sendMessage.errorMessage'))" regex="false">
                                       <then>
                                          <call-template target="responseHandlerTemplate">
                                             <with-param name="activity" value="nexmo_notifyCustomer" />
                                             <with-param name="id" value="{$ctx:id}" />
                                             <with-param name="status" value="success" />
                                             <with-param name="message" value="Customer has been notified about his/her loyalty balance." />
                                          </call-template>
                                          <!-- Update the custom field of the customer so that he is not mistakenly considered again. -->
                                          <vend.init>
                                             <apiUrl>{$ctx:vend.apiUrl}</apiUrl>
                                             <accessToken>{$ctx:vend.accessToken}</accessToken>
                                          </vend.init>
                                          <vend.updateCustomer>
                                             <customField1>{$ctx:vend.customerLoyalityBalance}</customField1>
                                             <customerId>{$ctx:vend.customerId}</customerId>
                                          </vend.updateCustomer>
                                          <sequence key="removeResponseHeaders" />
                                          <property name="vend.updatedCustomerId" expression="json-eval($.customer.id)" />
                                          <!-- START: Send a message to the customer only if the update fails -->
                                          <filter source="boolean(get-property('vend.updatedCustomerId'))" regex="false">
                                             <then>
                                                <property name="errorResponse" expression="json-eval($)" />
                                                <property name="status" value="error" />
                                                <call-template target="responseHandlerTemplate">
                                                   <with-param name="activity" value="vend_updateCustomer" />
                                                   <with-param name="id" value="{$ctx:id}" />
                                                   <with-param name="status" value="error" />
                                                   <with-param name="message" value="{$ctx:errorResponse}" />
                                                </call-template>
                                             </then>
                                          </filter>
                                          <!-- END: Send a message to the customer only if the update fails -->
                                       </then>
                                       <else>
                                          <property name="status" value="error" />
                                          <call-template target="responseHandlerTemplate">
                                             <with-param name="activity" value="nexmo_notifyCustomer" />
                                             <with-param name="id" value="{$ctx:id}" />
                                             <with-param name="status" value="error" />
                                             <with-param name="message" value="{$ctx:sendMessage.errorMessage}" />
                                          </call-template>
                                       </else>
                                    </filter>
                                    <!-- END: Proceed to update the custom field of the customer only if the SMS has been successfully sent. -->
                                 </then>
                              </filter>
                              <!-- END: Proceed if there is a change in the loyalty balance of the customer. -->
                           </then>
                        </filter>
                        <!-- END: Proceed only if the customer has loyalty enabled. -->
                        <!--Increment the customerIndex Count by 1 -->
                        <property name="customerIndex" expression="get-property('operation', 'customerIndex') + 1" scope="operation" />
                        <filter xpath="get-property('customerCount') = get-property('operation', 'customerIndex')">
                           <then>
                              <!-- START: Terminate the scenario if there are no new people in 'Vend' to add to the subscribers' list. -->
                              <filter source="boolean(get-property('mailchimp.batchEmailString'))" regex="false">
                                 <then>
                                    <call-template target="responseHandlerTemplate">
                                       <with-param name="activity" value="mailchimp_addPeopleToSubscribersList" />
                                       <with-param name="id" value="{$ctx:id.empty}" />
                                       <with-param name="status" value="skipped" />
                                       <with-param name="message" value="There are no new people in 'Vend' to add to the subscribers' list." />
                                    </call-template>
                                    <loopback />
                                 </then>
                              </filter>
                              <!-- END: Terminate the scenario if there are no new people in 'Vend' to add to the subscribers' list. -->
                              <!-- List the subscribers' list which match the provided list name -->
                              <mailchimp.init>
                                 <apiUrl>{$ctx:mailchimp.apiUrl}</apiUrl>
                                 <apiKey>{$ctx:mailchimp.apiKey}</apiKey>
                                 <format>json</format>
                              </mailchimp.init>
                              <mailchimp.listSubscriberLists>
                                 <listName>{$ctx:mailchimp.listName}</listName>
                                 <sortField>created</sortField>
                                 <sortDirection>DESC</sortDirection>
                              </mailchimp.listSubscriberLists>
                              <sequence key="removeResponseHeaders" />
                              <property name="mailchimp.listCount" expression="count(//data)" />
                              <!-- START: Proceed only if at least one list is returned. -->
                              <filter source="get-property('mailchimp.listCount')" regex="0.0">
                                 <then>
                                    <call-template target="responseHandlerTemplate">
                                       <with-param name="activity" value="mailchimp_getSubscribersList" />
                                       <with-param name="id" value="{$ctx:id.empty}" />
                                       <with-param name="status" value="Skipped" />
                                       <with-param name="message" value="There are no subscribers' list that match the name." />
                                    </call-template>
                                 </then>
                                 <else>
                                    <property name="mailchimp.listId" expression="//data[1]/id/text()" />
                                    <!-- Subscribe people to list -->
                                    <mailchimp.init>
                                       <apiUrl>{$ctx:mailchimp.apiUrl}</apiUrl>
                                       <apiKey>{$ctx:mailchimp.apiKey}</apiKey>
                                       <format>json</format>
                                    </mailchimp.init>
                                    <mailchimp.addSubscribersToList>
                                       <listId>{$ctx:mailchimp.listId}</listId>
                                       <batch>{$ctx:mailchimp.batchEmailString}</batch>
                                       <doubleOptin>false</doubleOptin>
                                       <updateExisting>true</updateExisting>
                                    </mailchimp.addSubscribersToList>
                                    <sequence key="removeResponseHeaders" />
                                    <property name="mailchimp.addCount" expression="json-eval($.add_count)" />
                                    <property name="id" expression="fn:concat('mailchimp_subscribersListId:', get-property('mailchimp.listId'))" />
                                    <filter xpath="get-property('mailchimp.addCount') &gt; 0">
                                       <then>
                                          <property name="status" value="success" />
                                          <property name="message" expression="fn:concat(get-property('mailchimp.addCount'), ' subscriber(s) have been added to the list.')" />
                                       </then>
                                       <else>
                                          <property name="status" value="skipped" />
                                          <property name="message" value="All customers are already members of the subscribers' list." />
                                       </else>
                                    </filter>
                                    <call-template target="responseHandlerTemplate">
                                       <with-param name="activity" value="mailchimp_addCustomersToSubscribersList" />
                                       <with-param name="id" value="{$ctx:id}" />
                                       <with-param name="status" value="{$ctx:status}" />
                                       <with-param name="message" value="{$ctx:message}" />
                                    </call-template>
                                    <property name="mailchimp.errorCount" expression="json-eval($.error_count)" />
                                    <filter xpath="get-property('mailchimp.errorCount') &gt; 0">
                                       <then>
                                          <property name="message" expression="json-eval($.errors)" />
                                          <call-template target="responseHandlerTemplate">
                                             <with-param name="activity" value="mailchimp_addPeopleToSubscribersList" />
                                             <with-param name="id" value="{$ctx:id}" />
                                             <with-param name="status" value="error" />
                                             <with-param name="message" value="{$ctx:message}" />
                                          </call-template>
                                       </then>
                                    </filter>
                                 </else>
                              </filter>
                              <!-- END: Proceed only if at least one list is returned. -->
                              <loopback />
                           </then>
                        </filter>
                     </sequence>
                  </target>
               </iterate>
               <!--FOR EACH Customer - END -->
            </then>
            <else>
               <property name="skipMessage" expression="fn:concat('There are no customers created/modified since ', get-property('vend.considerSince'), '.')" />
               <!-- Append a skip message to be sent to the user if there aren't any products to be processed. -->
               <call-template target="responseHandlerTemplate">
                  <with-param name="activity" value="vend_updateCustomerBaseAndNotifyLoyaltyBalance" />
                  <with-param name="id" value="{$ctx:id.empty}" />
                  <with-param name="status" value="skipped" />
                  <with-param name="message" value="{$ctx:skipMessage}" />
               </call-template>
               <loopback />
            </else>
         </filter>
         <!-- END: Proceed only if there are any customers to process. -->
      </inSequence>
      <outSequence>
         <!-- Send the constructed response to the user. -->
         <payloadFactory media-type="json">
            <format>
               {
               "Response":{
               "process":"vend_updateCustomerBaseAndNotifyLoyaltyBalance",
               "activityResponse": [$1]
               }
               }
            </format>
            <args>
               <arg expression="get-property('operation', 'responseString')" />
            </args>
         </payloadFactory>
         <send />
      </outSequence>
   </target>
</proxy>
Sample request for updating MailChimp subscribers’ lists with the customers in Vend and notifying customers in Vend regarding changes in their loyalty balance via SMS
{
   "vend":{
      "considerSince":"2015-09-28 00:00:00",
      "fromName":"Yasvini Trolleys"
   },
   "mailchimp":{
      "listName":"Cotton Connections Subscriber List"
   }
}

Note

 The following are the parameter descriptions:

  • vend.considerSince: (Optional) Customers who are created/modified only after this date-time is considered for the case. If the parameter is not provided, it will be defaulted to 7 days prior to the execution of the scenario.
  • vend.fromName: Name of the company/person to be used as the sender name for the SMS messages.
  • mailchimp.listName: Name of the subscribers' list in MailChimp to which the customers would be added/updated.

Retrieving monthly registered sales, creating gift packs, creating routes and notifying customers

Note

A payment type called 'Gift Voucher' should be created in the Vend account prior to executing the scenario.

  1. Retrieve the details of the product from the Vend API using the getProduct operation.
  2. Retrieve all the outlets in the Vend API using the listOutlets operation.
  3. Retrieve all the registered sales for the outlet from the Vend API using the listRegisterSales operation.
  4. Retrieve the details of the customer (by ID) from the Vend API using the listCustomers operation.
  5. Create a register sale for the gift pack in the Vend API using the createRegisterSale operation.
  6. Retrieve the details of the particular customer from the Vend API using the listCustomers operation.
  7. Create the route in the Beetrack API using the createRoute operation.
  8. Update the custom field of the customer in the Vend API using the updateCustomer operation.
  9. Notify the customer about the gift pack via e-mail using the sendMessage operation in the Mandrill API.
  10. Notify the customer about the gift pack via SMS using the sendMessage operation in the Nexmo API.
Vend operations
Beetrack operations
Nexmo operations
Mandrill operations
Samples 
Sample Template for creating a gift pack for the specified customer, creating a delivery route for the gift pack and notifying them via e-mail and SMS
<?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 creates a gift pack for the specified customer, creates a delivery route for the gift pack and notifies them via email and SMS. -->
<template name="vend-rewardCustomerWithGiftPack" xmlns="http://ws.apache.org/ns/synapse">
   <!-- Vend properties -->
   <parameter name="vend.apiUrl" description="Base endpoint URL of Vend API." />
   <parameter name="vend.accessToken" description="Access Token to read and manipulate data of Vend account." />
   <parameter name="vend.fullProducts" description="Array of product objects." />
   <parameter name="vend.products" description="Array of products to include in the gift pack." />
   <parameter name="vend.customerId" description="ID of the customer who is entitled to the reward." />
   <parameter name="vend.paymentTypeId" description="ID payment type to be used for the gift pack." />
   <parameter name="vend.registerId" description="ID of the register in which the sale for the gift pack will be recorded." />
   <parameter name="vend.fromName" description="From name to be used for email and SMS." />
   <parameter name="vend.fromEmail" description="From email to be used for emails." />
   <parameter name="vend.salesSince" description="Since date to retrieve sales." />
   <parameter name="vend.salesAmount" description="Amount of the sales done by the customer." />
   <parameter name="vend.customerPosition" description="Position of the customer." />
   <!-- Nexmo properties -->
   <parameter name="nexmo.apiUrl" description="The url to access the Nexmo API." />
   <parameter name="nexmo.apiKey" description="The apiKey of a valid Nexmo account." />
   <parameter name="nexmo.apiSecret" description="The apiSecret of a valid Nexmo account." />
   <!-- Mandrill properties -->
   <parameter name="mandrill.apiKey" description="API Key to access data of Mandrill account." />
   <parameter name="mandrill.apiUrl" description="Base endpoint URL of Mandrill API." />
   <!-- Beetrack properties -->
   <parameter name="beetrack.apiUrl" description="Base endpoint URL of Beetrack API." />
   <parameter name="beetrack.accessToken" description="Access Token to read and manipulate data of Beetrack account." />
   <parameter name="beetrack.vehicleId" description="ID of the vehicle using which the delivery would be made." />
   <sequence>
      <property name="vend.apiUrl" expression="$func:vend.apiUrl" />
      <property name="vend.accessToken" expression="$func:vend.accessToken" />
      <property name="vend.fullProducts" expression="$func:vend.fullProducts" />
      <property name="vend.products" expression="$func:vend.products" />
      <property name="vend.customerId" expression="$func:vend.customerId" />
      <property name="vend.paymentTypeId" expression="$func:vend.paymentTypeId" />
      <property name="vend.registerId" expression="$func:vend.registerId" />
      <property name="vend.fromName" expression="$func:vend.fromName" />
      <property name="vend.fromEmail" expression="$func:vend.fromEmail" />
      <property name="vend.salesSince" expression="$func:vend.salesSince" />
      <property name="vend.salesAmount" expression="$func:vend.salesAmount" />
      <property name="vend.customerPosition" expression="$func:vend.customerPosition" />
      <property name="nexmo.apiUrl" expression="$func:nexmo.apiUrl" />
      <property name="nexmo.apiKey" expression="$func:nexmo.apiKey" />
      <property name="nexmo.apiSecret" expression="$func:nexmo.apiSecret" />
      <property name="mandrill.apiKey" expression="$func:mandrill.apiKey" />
      <property name="mandrill.apiUrl" expression="$func:mandrill.apiUrl" />
      <property name="beetrack.apiUrl" expression="$func:beetrack.apiUrl" />
      <property name="beetrack.accessToken" expression="$func:beetrack.accessToken" />
      <property name="beetrack.vehicleId" expression="$func:beetrack.vehicleId" />
      <!-- Get the details of the customer (by ID). -->
      <vend.init>
         <apiUrl>{$ctx:vend.apiUrl}</apiUrl>
         <accessToken>{$ctx:vend.accessToken}</accessToken>
      </vend.init>
      <vend.listCustomers>
         <id>{$ctx:vend.customerId}</id>
      </vend.listCustomers>
      <sequence key="removeResponseHeaders" />
      <!-- Verify whether the customer has already been rewarded within the given time range. Ignore the customer if already rewarded. -->
      <script language="js">
         <![CDATA[
            var lastRewardedDate = mc.getPayloadJSON().customers[0].custom_field_2;
            var salesSince = mc.getProperty('vend.salesSince');
            var dateFormat = 'yyyy-MM-dd hh:mm:ss';
            
            // Proceed if 'custom_field_2' of the customer is empty.
            if(lastRewardedDate != ''){
               // Proceed only if the customer was not rewarded before, within the given time range.
               if(new java.text.SimpleDateFormat(dateFormat).parse(lastRewardedDate).getTime()
                     > new java.text.SimpleDateFormat(dateFormat).parse(salesSince).getTime()){
                  mc.setProperty('proceed', false);
                  mc.setProperty('timeRange', '(' + salesSince + ' - ' + new java.text.SimpleDateFormat(dateFormat).format(new java.util.Date()) + ')');
               } else {
                  mc.setProperty('proceed', true);
               }
            } else {
               mc.setProperty('proceed', true);
            }        
            mc.setProperty('vend.salesAmount', new java.lang.Double(mc.getProperty('vend.salesAmount')));    
         ]]>
      </script>
      <!-- START: Proceed only if the customer was not rewarded before, within the given time range. -->
      <filter source="get-property('proceed')" regex="false">
         <then>
            <!-- Append a skip message to be sent to the user. -->
            <property name="id" expression="fn:concat('vend_customerId:', get-property('vend.customerId'))" />
            <property name="message" expression="fn:concat('The customer has already been rewarded for the specified time period ', get-property('timeRange'), '.')" />
            <call-template target="responseHandlerTemplate">
               <with-param name="activity" value="vend_createAndSendGiftPack" />
               <with-param name="id" value="{$ctx:id}" />
               <with-param name="status" value="skipped" />
               <with-param name="message" value="{$ctx:message}" />
            </call-template>
         </then>
         <else>
            <!-- Iterate over the products and create the products array in order to create the register sale. -->
            <script language="js">
               <![CDATA[
                  var fullProducts = eval("(" + mc.getProperty('vend.fullProducts') + ")");
                  var products = eval("(" + mc.getProperty('vend.products') + ")");
                  var productsArray = [];
                  
                  if(products.length > 0){
                     for(var i=0; i<products.length; i++){
                        var product = {};
                        product.product_id = products[i].id;
                        product.quantity = products[i].quantity;
                        productsArray[i] = product;
                     }
                  }
                  
                  var jsonPayload = {};
                  jsonPayload.products = productsArray;
                  mc.setPayloadJSON(jsonPayload);       
                  
                  mc.setProperty('vend.lastRewardedDate', new java.text.SimpleDateFormat('yyyy-MM-dd hh:mm:ss').format(new java.util.Date()));                             
               ]]>
            </script>
            <property name="vend.productsArray" expression="json-eval($.products)" />
            <!-- START: Proceed only if the user has specified at least one product to be included in the gift pack. -->
            <filter xpath="get-property('vend.productsArray') != '[]'">
               <then>
                  <!-- Create the payment object to be used for the 'createRegisterSale' method. -->
                  <script language="js">
                     <![CDATA[
                        var paymentTypeId = mc.getProperty('vend.paymentTypeId');
                        var orderDate = new java.text.SimpleDateFormat('yyyy-MM-dd hh:mm:ss').format(new java.util.Date());
                        mc.setProperty('vend.orderDate', orderDate);
                        
                        var paymentObject = {};
                        paymentObject.retailer_payment_type_id = paymentTypeId;
                        paymentObject.payment_date = orderDate;
                        mc.setPayloadJSON(paymentObject);
                     ]]>
                  </script>
                  <property name="vend.registerSalePayments" expression="json-eval($)" />
                  <property name="vend.registerSalePayments" expression="fn:concat('[', get-property('vend.registerSalePayments'), ']')" />
                  <property name="vend.saleNote" value="The sale was created with the products that are to be sent to the customer in a gift pack." />
                  <!-- Create a register sale for the gift pack. -->
                  <vend.init>
                     <apiUrl>{$ctx:vend.apiUrl}</apiUrl>
                     <accessToken>{$ctx:vend.accessToken}</accessToken>
                  </vend.init>
                  <vend.createRegisterSale>
                     <registerId>{$ctx:vend.registerId}</registerId>
                     <customerId>{$ctx:vend.customerId}</customerId>
                     <saleDate>{$ctx:vend.orderDate}</saleDate>
                     <userName>admin</userName>
                     <status>ONACCOUNT_CLOSED</status>
                     <note>{$ctx:vend.saleNote}</note>
                     <registerSaleProducts>{$ctx:vend.productsArray}</registerSaleProducts>
                     <registerSalePayments>{$ctx:vend.registerSalePayments}</registerSalePayments>
                  </vend.createRegisterSale>
                  <sequence key="removeResponseHeaders" />
                  <property name="vend.registerSaleId" expression="json-eval($.register_sale.id)" />
                  <!-- START: Proceed to create the route only if the gift pack was successfully created. -->
                  <filter source="boolean(get-property('vend.registerSaleId'))" regex="false">
                     <then>
                        <property name="id" expression="fn:concat('vend_customerId:', get-property('vend.customerId'))" />
                        <property name="errorResponse" expression="json-eval($)" />
                        <!-- Append a error message to be sent to the user if createRegisterSale method failed. -->
                        <call-template target="responseHandlerTemplate">
                           <with-param name="activity" value="vend_createRegisterSale" />
                           <with-param name="id" value="{$ctx:id}" />
                           <with-param name="status" value="error" />
                           <with-param name="message" value="{$ctx:errorResponse}" />
                        </call-template>
                     </then>
                     <else>
                        <!-- Get the details of the particular customer. -->
                        <vend.init>
                           <apiUrl>{$ctx:vend.apiUrl}</apiUrl>
                           <accessToken>{$ctx:vend.accessToken}</accessToken>
                        </vend.init>
                        <vend.listCustomers>
                           <id>{$ctx:vend.customerId}</id>
                        </vend.listCustomers>
                        <sequence key="removeResponseHeaders" />
                        <!-- Construct the dispatch object to create the route. -->
                        <script language="js">
                           <![CDATA[
                              var fullProducts = eval("(" + mc.getProperty('vend.fullProducts') + ")");
                              var products = eval("(" + mc.getProperty('vend.products') + ")");
                              
                              var customer = mc.getPayloadJSON().customers[0];
                              var dispatchObject = {};
                              dispatchObject.identifier = customer.customer_code;
                              var customerName = customer.first_name + ' ' + customer.last_name;
                              dispatchObject.contact_name = customerName;
                              mc.setProperty('vend.customerName', customerName);
                              mc.setProperty('vend.customerFirstName', customer.first_name);
                              
                              dispatchObject.contact_address = customer.postal_address1 + ' ' + customer.postal_address2 + ' ' + customer.postal_city + ' ' + customer.postal_state + ' ' + customer.postal_postcode + ' ' + customer.postal_country_id;
                              dispatchObject.contact_phone = customer.mobile;
                              mc.setProperty('vend.customerPhone', customer.mobile);
                              
                              dispatchObject.contact_id = customer.id;
                              dispatchObject.contact_email = customer.email;
                              mc.setProperty('vend.customerEmail', customer.email);
                              
                              dispatchObject.slot = 0;
                              mc.setProperty('beetrack.estimatedDate', new java.text.SimpleDateFormat('yyyy-MM-dd hh:mm:ss').format(java.util.Date(new java.util.Date().getTime() + 259200000)));
                              
                              var items = [];
                              for(var i=0; i<products.length; i++){
                                 var item = {};
                                 var fullItem = fullProducts[products[i].id];
                                 item.code = fullItem.sku;
                                 if(new java.lang.String(fullItem.description).startsWith('<')){
                                    var length = new java.lang.String(fullItem.description).length();
                                    item.description = new java.lang.String(fullItem.description).substring(3, length-4);
                                 } 
                                 item.quantity = products[i].quantity;
                                 items[i] = item;
                              }
                              
                              dispatchObject.items = items;
                              mc.setPayloadJSON(dispatchObject);
                           ]]>
                        </script>
                        <property name="beetrack.dispatchObject" expression="json-eval($)" />
                        <property name="beetrack.dispatchObject" expression="fn:concat('[', get-property('beetrack.dispatchObject'), ']')" />
                        <!-- Create the route in Beetrack. -->
                        <beetrack.init>
                           <apiUrl>{$ctx:beetrack.apiUrl}</apiUrl>
                           <accessToken>{$ctx:beetrack.accessToken}</accessToken>
                        </beetrack.init>
                        <beetrack.createRoute>
                           <truckIdentifier>{$ctx:beetrack.vehicleId}</truckIdentifier>
                           <date>{$ctx:beetrack.estimatedDate}</date>
                           <dispatches>{$ctx:beetrack.dispatchObject}</dispatches>
                           <enableEstimations>false</enableEstimations>
                        </beetrack.createRoute>
                        <sequence key="removeResponseHeaders" />
                        <property name="beetrack.routId" expression="$axis2:HTTP_SC" />
                        <!-- START: Proceed to notify the customer only if the route was created successfully. -->
                        <filter source="boolean(get-property('beetrack.routId'))" regex="false">
                           <then>
                              <!-- Append a success message to be sent to the user if the sale was successfully created. -->
                              <property name="id" expression="fn:concat('vend_customerId:', get-property('vend.customerId'), ',vend_registerSaleId:', get-property('vend.registerSaleId'))" />
                              <property name="errorResponse" expression="json-eval($)" />
                              <call-template target="responseHandlerTemplate">
                                 <with-param name="activity" value="vend_createAndSendGiftPack" />
                                 <with-param name="id" value="{$ctx:id}" />
                                 <with-param name="status" value="error" />
                                 <with-param name="message" value="Gift pack has been successfully created but an error occured while creating a delivery route for it." />
                              </call-template>
                           </then>
                           <else>
                              <!-- Append a success message to be sent to the user if the route was successfully created. -->
                              <property name="id" expression="fn:concat('vend_customerId:', get-property('vend.customerId'), ',vend_registerSaleId:', get-property('vend.registerSaleId'), ',beetrack_routeId:', get-property('beetrack.routId'))" />
                              <property name="message" expression="fn:concat('Gift pack has been successfully created (position: ', get-property('vend.customerPosition'), ', sales: USD ', get-property('vend.salesAmount'), ') and arranged for delivery.')" />
                              <call-template target="responseHandlerTemplate">
                                 <with-param name="activity" value="vend_createAndSendGiftPack" />
                                 <with-param name="id" value="{$ctx:id}" />
                                 <with-param name="status" value="success" />
                                 <with-param name="message" value="{$ctx:message}" />
                              </call-template>
                              <property name="uri.var.note" action="remove" />
                              <!-- Update the custom field of the customer so that he is not mistakenly considered again. -->
                              <vend.init>
                                 <apiUrl>{$ctx:vend.apiUrl}</apiUrl>
                                 <accessToken>{$ctx:vend.accessToken}</accessToken>
                              </vend.init>
                              <vend.updateCustomer>
                                 <customField2>{$ctx:vend.lastRewardedDate}</customField2>
                                 <customerId>{$ctx:vend.customerId}</customerId>
                              </vend.updateCustomer>
                              <sequence key="removeResponseHeaders" />
                              <!-- Construct the email to notify the customer. -->
                              <script language="js">
                                 <![CDATA[
                                    var customerEmail = mc.getProperty('vend.customerEmail');                      
                                    var customerFirstName = mc.getProperty('vend.customerFirstName'); 
                                    
                                    var mailHTMLUser = '<h3>Dear ' + customerFirstName + ",</h3><p><strong>Congratulations!</strong></p><p>We are delighted to inform you that you have been chosen as one of our most valued customers. As a token of gratitude for your transactions with us, we have sent you a surprise gift pack... to your home of course!</p><p>We would also like to take this opportunity to thank you for the continuous trust you have placed on us and we are going to be delighted to strengthen our relationship further. We're dedicated to serve you more and more and we humbly ask you to continue buying our products in future.</p><p><strong>Cheers and have Fun!</strong></p><p>`</p><p>Please do not hesitate to call our customer care agents in case you didn't recieve the gift pack within the next 3 business days.</p><p>This is an auto-generated email. Please do not reply.</p>";
                                    mc.setProperty('mandrill.htmlUser', mailHTMLUser); 
                                                                              
                                    mc.setProperty('mandrill.subject', 'Congratulations! You have a gift pack waiting for you...!');
                                    
                                    var mailToUser = '[{"email": "' + customerEmail + '", "name": "' + customerFirstName + '", "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;')" />
                              <!-- Notify the customer about the gift pack via email. -->
                              <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:vend.fromEmail}</fromEmail>
                                 <fromName>{$ctx:vend.fromName}</fromName>
                                 <to>{$ctx:mandrill.toUser}</to>
                              </mandrill.sendMessage>
                              <sequence key="removeResponseHeaders" />
                              <property name="mandrill.mailIdUser" expression="json-eval($[0]._id)" />
                              <property name="mandrill.errorMessage" expression="json-eval($[0].reject_reason)" />
                              <property name="nexmo.text" expression="fn:concat('Hi ', get-property('vend.customerFirstName'), ', Congratulations! You have won a gift pack for being one of our premium customers. Await a gift at your doorstep within the next 3 days...! Check your mail inbox for more information.')" />
                              <!-- Notify customer about the gift pack via SMS. -->
                              <nexmo.init>
                                 <responseType>json</responseType>
                                 <apiUrl>{$ctx:nexmo.apiUrl}</apiUrl>
                                 <apiSecret>{$ctx:nexmo.apiSecret}</apiSecret>
                                 <apiKey>{$ctx:nexmo.apiKey}</apiKey>
                              </nexmo.init>
                              <nexmo.sendMessage>
                                 <to>{$ctx:vend.customerPhone}</to>
                                 <text>{$ctx:nexmo.text}</text>
                                 <from>{$ctx:vend.fromName}</from>
                                 <type>text</type>
                              </nexmo.sendMessage>
                              <sequence key="removeResponseHeaders" />
                              <property name="sendMessage.errorMessage" expression="json-eval($.messages[0].error-text)" />
                              <property name="id" expression="fn:concat('vend_customerId:', get-property('vend.customerId'), ',vend_registerSaleId:', get-property('vend.registerSaleId'))" />
                              <!-- START: Append a message to be sent to the user regarding the status of the send email and send sms operation. -->
                              <filter source="boolean(get-property('mandrill.mailIdUser'))" regex="true">
                                 <then>
                                    <filter source="boolean(get-property('sendMessage.errorMessage'))" regex="false">
                                       <then>
                                          <property name="status" value="success" />
                                          <property name="message" value="Customer has been notified about the gift pack." />
                                       </then>
                                       <else>
                                          <property name="status" value="error" />
                                          <property name="message" expression="fn:concat('Customer has been notified about the gift pack via email, but an error occured while sending SMS (', get-property('sendMessage.errorMessage'), ').')" />
                                       </else>
                                    </filter>
                                 </then>
                                 <else>
                                    <filter source="boolean(get-property('sendMessage.errorMessage'))" regex="false">
                                       <then>
                                          <property name="status" value="error" />
                                          <property name="message" expression="fn:concat('Customer has been notified about the gift pack via SMS, but an error occured while sending email (', get-property('mandrill.errorMessage'), ').')" />
                                       </then>
                                       <else>
                                          <property name="status" value="error" />
                                          <property name="message" expression="fn:concat('Unknown error occured while notifying the customer about the gift pack via email (', get-property('mandrill.errorMessage'), ') and SMS (', get-property('sendMessage.errorMessage'), ').')" />
                                       </else>
                                    </filter>
                                 </else>
                              </filter>
                              <!-- END: Append a message to be sent to the user regarding the status of the send email and send sms operation. -->
                              <call-template target="responseHandlerTemplate">
                                 <with-param name="activity" value="vend_notifyCustomer" />
                                 <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 to notify the customer only if the route was created successfully. -->
                     </else>
                  </filter>
                  <!-- END: Proceed to create the route only if the gift pack was successfully created. -->
               </then>
               <else>
                  <!-- Append a skip message to be sent to the user. -->
                  <property name="id" expression="fn:concat('vend_customerId:', get-property('vend.customerId'))" />
                  <call-template target="responseHandlerTemplate">
                     <with-param name="activity" value="vend_createAndSendGiftPack" />
                     <with-param name="id" value="{$ctx:id}" />
                     <with-param name="status" value="skipped" />
                     <with-param name="message" value="No products have been specified to reward the customer." />
                  </call-template>
               </else>
            </filter>
            <!-- END: Proceed only if the user has specified at least one product to be included in the gift pack. -->
         </else>
      </filter>
      <!-- END: Proceed only if the customer was not rewarded before, within the given time range. -->
   </sequence>
</template>
Sample Proxy for discovering premium customers based on sales, creating a gift pack for them to be sent as a reward, creating a route in Beetrack for the gift pack to be delivered to the customer and notifying the customer about the reward via e-mail and SMS
<?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 scenario finds the top customers for a given date range and creates rewards for them. -->
<proxy xmlns="http://ws.apache.org/ns/synapse" name="vend_discoverPremiumCustomersAndReward" transports="http,https" startOnLoad="true" trace="disable">
   <target>
      <inSequence onError="faultHandlerSeq">
         <!-- Vend Properties -->
         <property name="vend.salesSince" expression="json-eval($.vend.salesSince)" />
         <property name="vend.minimumSalesAmount" expression="json-eval($.vend.minimumSalesAmount)" />
         <property name="vend.fromName" expression="json-eval($.vend.fromName)" />
         <property name="vend.fromEmail" expression="json-eval($.vend.fromEmail)" />
         <property name="vend.registerId" expression="json-eval($.vend.registerId)" />
         <property name="vend.productsForFirstCustomer" expression="json-eval($.vend.firstCustomer.products)" />
         <property name="vend.minimumCustomersForFirst" expression="json-eval($.vend.firstCustomer.minimumCustomers)" />
         <property name="vend.productsForSecondCustomer" expression="json-eval($.vend.secondCustomer.products)" />
         <property name="vend.minimumCustomersForSecond" expression="json-eval($.vend.secondCustomer.minimumCustomers)" />
         <property name="vend.productsForThirdCustomer" expression="json-eval($.vend.thirdCustomer.products)" />
         <property name="vend.minimumCustomersForThird" expression="json-eval($.vend.thirdCustomer.minimumCustomers)" />
         <!-- Beetrack Properties -->
         <property name="beetrack.apiUrl" expression="get-property('registry', 'connectors/Beetrack/apiUrl')" />
         <property name="beetrack.accessToken" expression="get-property('registry', 'connectors/Beetrack/accessToken')" />
         <property name="beetrack.vehicleId" expression="json-eval($.beetrack.vehicleId)" />
         <!-- Mandrill Properties -->
         <property name="mandrill.apiUrl" expression="get-property('registry', 'connectors/Mandrill/apiUrl')" />
         <property name="mandrill.apiKey" expression="get-property('registry', 'connectors/Mandrill/apiKey')" />
         <!-- Nexmo Properties -->
         <property name="nexmo.apiUrl" expression="get-property('registry', 'connectors/Nexmo/apiUrl')" />
         <property name="nexmo.apiSecret" expression="get-property('registry', 'connectors/Nexmo/apiSecret')" />
         <property name="nexmo.apiKey" expression="get-property('registry', 'connectors/Nexmo/apiKey')" />
         <!-- Default value for 'vend.minimumCustomersForFirst' is 1 -->
         <filter source="boolean(get-property('vend.minimumCustomersForFirst'))" regex="false">
            <then>
               <property name="vend.minimumCustomersForFirst" value="1" />
            </then>
         </filter>
         <!-- Default value for 'vend.minimumCustomersForSecond' is 2 -->
         <filter source="boolean(get-property('vend.minimumCustomersForSecond'))" regex="false">
            <then>
               <property name="vend.minimumCustomersForSecond" value="2" />
            </then>
         </filter>
         <!-- Default value for 'vend.minimumCustomersForThird' is 3 -->
         <filter source="boolean(get-property('vend.minimumCustomersForThird'))" regex="false">
            <then>
               <property name="vend.minimumCustomersForThird" value="3" />
            </then>
         </filter>
         <!-- Default value for 'vend.minimumSalesAmount' is 0 -->
         <filter source="boolean(get-property('vend.minimumSalesAmount'))" regex="false">
            <then>
               <property name="vend.minimumSalesAmount" value="0" />
            </then>
         </filter>
         <property name="id.empty" value="{}" />
         <property name="rewardedCustomers" expression="0" scope="operation" />
         <vend.init />
         <vend.listPaymentTypes />
         <sequence key="removeResponseHeaders" />
         <property name="vend.apiUrl" expression="get-property('registry', 'connectors/Vend/apiUrl')" />
         <property name="vend.accessToken" expression="get-property('registry', 'connectors/Vend/accessToken')" />
         <!-- Iterate over the payment types and extract the ID of the required type. -->
         <script language="js">
            <![CDATA[
               var paymentTypes = mc.getPayloadJSON().payment_types;
               var giftVoucherPaymentId = '';
               
               if(paymentTypes.length > 0){
                  for(var i=0; i<paymentTypes.length; i++){
                     if(paymentTypes[i].name.toLowerCase() == 'gift voucher'){
                        giftVoucherPaymentId = paymentTypes[i].id;
                        break;
                     }
                  }
               }
               
               mc.setProperty('vend.giftVoucherPaymentId', giftVoucherPaymentId);               
            ]]>
         </script>
         <!-- START: Terminate the scenario if a payment type called 'Gift Voucher'doesn't exist in Vend account. -->
         <filter source="boolean(get-property('vend.giftVoucherPaymentId'))" regex="false">
            <then>
               <!-- Append an skip message to be sent to the user if 'Gift Voucher' payment type doesn't exist. -->
               <call-template target="responseHandlerTemplate">
                  <with-param name="activity" value="vend_getPaymentTypeForGiftVouchers" />
                  <with-param name="id" value="{$ctx:id.empty}" />
                  <with-param name="status" value="skipped" />
                  <with-param name="message" value="A custom payment type called 'Gift Voucher' is not found in the system. Please create the payment type and try again." />
               </call-template>
               <loopback />
            </then>
         </filter>
         <!-- END: Terminate the scenario if a payment type called 'Gift Voucher'doesn't exist in Vend account. -->
         <!-- START: If the user has not provided the last modified date, use the 00:00:00 am of the current day. -->
         <filter source="boolean(get-property('vend.salesSince'))" regex="false">
            <then>
               <script language="js">
                  <![CDATA[
                     // 2592000000 - 30 days in milliseconds.
                     var salesSince = new java.text.SimpleDateFormat('yyyy-MM-dd hh:mm:ss').format(java.util.Date(new java.util.Date().getTime() - 2592000000));
                     mc.setProperty('vend.salesSince', salesSince);                     
                  ]]>
               </script>
            </then>
         </filter>
         <!-- END: If the user has not provided the last modified date, use the 00:00:00 am of the current day. -->
         <!-- Combine all the 3 products array into one and set to payload for iterations. -->
         <script language="js">
            <![CDATA[
               var products = [];
            
               var firstCustomerProducts = mc.getProperty('vend.productsForFirstCustomer');
               if(firstCustomerProducts != null && firstCustomerProducts != ''){
                  firstCustomerProducts = eval("(" + firstCustomerProducts + ")")
                  mc.setProperty('noOfFirstCustomerProducts', firstCustomerProducts.length);
                  if(firstCustomerProducts.length > 0){
                     for(var i=0; i<firstCustomerProducts.length; i++){
                        products.push(firstCustomerProducts[i]);
                     }                     
                  }
               }
               
               var secondCustomerProducts = mc.getProperty('vend.productsForSecondCustomer');
               if(secondCustomerProducts != null && secondCustomerProducts != ''){
                  secondCustomerProducts = eval("(" + secondCustomerProducts + ")")
                  mc.setProperty('noOfSecondCustomerProducts', secondCustomerProducts.length);
                  if(secondCustomerProducts.length > 0){
                     for(var i=0; i<secondCustomerProducts.length; i++){
                        products.push(secondCustomerProducts[i]);
                     }                     
                  }
               }
               
               var thirdCustomerProducts = mc.getProperty('vend.productsForThirdCustomer');
               if(thirdCustomerProducts != null && thirdCustomerProducts != ''){
                  thirdCustomerProducts = eval("(" + thirdCustomerProducts + ")")
                  mc.setProperty('noOfThirdCustomerProducts', thirdCustomerProducts.length);
                  if(thirdCustomerProducts.length > 0){
                     for(var i=0; i<thirdCustomerProducts.length; i++){
                        products.push(thirdCustomerProducts[i]);
                     }                     
                  }
               }
               
               var productsObject = {};
               productsObject.products = products;
               mc.setPayloadJSON(productsObject);
            ]]>
         </script>
         <property name="productCount" expression="count(//products)" />
         <!-- START: Terminate the scenario if the user has not sent at least one gift product. -->
         <filter source="get-property('productCount')" regex="0.0">
            <then>
               <!-- Append an skip message to be sent to the user if no gift products have been specified. -->
               <call-template target="responseHandlerTemplate">
                  <with-param name="activity" value="vend_discoverPremiumCustomersAndReward" />
                  <with-param name="id" value="{$ctx:id.empty}" />
                  <with-param name="status" value="skipped" />
                  <with-param name="message" value="There has to be at least one gift product specified in the request." />
               </call-template>
               <loopback />
            </then>
         </filter>
         <!-- END: Terminate the scenario if the user has not sent at least one gift product. -->
         <property name="productIndex" expression="0" scope="operation" />
         <property name="fullProducts" value="{}" scope="operation" />
         <!-- FOR EACH Product : BEGIN -->
         <iterate continueParent="false" id="products" expression="//products" sequential="true">
            <target>
               <sequence>
                  <property name="vend.productId" expression="//id/text()" />
                  <property name="fullProducts" expression="get-property('operation', 'fullProducts')" />
                  <!-- Check whether the current product needs to be processed (if it is not already processed). -->
                  <script language="js">
                     <![CDATA[
                        var productId = mc.getProperty('vend.productId');
                        var fullProducts = eval("(" + mc.getProperty('fullProducts') + ")");
                        
                        if(fullProducts.hasOwnProperty(productId)){
                           mc.setProperty('proceed', false);
                        } else {
                           mc.setProperty('proceed', true);
                        }
                     ]]>
                  </script>
                  <property name="fullProducts" action="remove" />
                  <!-- START: Proceed only if the product is not already retrieved. -->
                  <filter source="get-property('proceed')" regex="true">
                     <then>
                        <!-- Retrieve the details of the product y ID. -->
                        <vend.init>
                           <apiUrl>{$ctx:vend.apiUrl}</apiUrl>
                           <accessToken>{$ctx:vend.accessToken}</accessToken>
                        </vend.init>
                        <vend.getProduct>
                           <productId>{$ctx:vend.productId}</productId>
                        </vend.getProduct>
                        <sequence key="removeResponseHeaders" />
                        <property name="vend.retrievedProductId" expression="json-eval($.products[0].id)" />
                        <!-- START: Proceed only if the product could be retrieved, else terminate the scenario. -->
                        <filter xpath="get-property('vend.productId') != get-property('vend.retrievedProductId')">
                           <then>
                              <!-- Append a skip message to be sent to the user if any of the product IDs passed are invalid or references and invalid product. -->
                              <property name="id" expression="fn:concat('vend_productId:', get-property('vend.productId'))" />
                              <call-template target="responseHandlerTemplate">
                                 <with-param name="activity" value="vend_getGiftProductDetails" />
                                 <with-param name="id" value="{$ctx:id}" />
                                 <with-param name="status" value="skipped" />
                                 <with-param name="message" value="No such product exists in Vend." />
                              </call-template>
                              <loopback />
                           </then>
                           <else>
                              <property name="fullProducts" expression="get-property('operation', 'fullProducts')" />
                              <!-- Extract the required details from the product and create a new simple object. -->
                              <script language="js">
                                 <![CDATA[
                                    var product = mc.getPayloadJSON().products[0];
                                    var fullProducts = eval("(" + mc.getProperty('fullProducts') + ")");
                                    
                                    var newProduct = {};
                                    newProduct.sku = product.sku;
                                    newProduct.description = product.description;
                                    fullProducts[product.id] = newProduct;
                                    mc.setPayloadJSON(fullProducts);
                                 ]]>
                              </script>
                              <property name="fullProducts" expression="json-eval($)" scope="operation" />
                           </else>
                        </filter>
                        <!-- END: Proceed only if the product could be retrieved, else terminate the scenario. -->
                     </then>
                  </filter>
                  <!-- END: Proceed only if the product is not already retrieved. -->
                  <!--Increment the productIndex count by 1 -->
                  <property name="productIndex" expression="get-property('operation','productIndex') + 1" scope="operation" />
                  <!-- START: Proceed with the remainder of the scenarios once all the gift products are processed. -->
                  <filter xpath="get-property('productCount') = get-property('operation', 'productIndex')">
                     <then>
                        <!-- Retrieve all the outlets in Vend. -->
                        <vend.init>
                           <apiUrl>{$ctx:vend.apiUrl}</apiUrl>
                           <accessToken>{$ctx:vend.accessToken}</accessToken>
                        </vend.init>
                        <vend.listOutlets />
                        <sequence key="removeResponseHeaders" />
                        <property name="listOutlets.statusCode" expression="$axis2:HTTP_SC" />
                        <!-- START: Proceed only if the listOutlets call is successful. -->
                        <filter xpath="get-property('listOrders.statusCode') != 200">
                           <then>
                              <property name="errorMessage" expression="json-eval($)" />
                              <!-- Append an error message to be sent to the user regarding listOutlets method call. -->
                              <call-template target="responseHandlerTemplate">
                                 <with-param name="activity" value="vend_listOutlets" />
                                 <with-param name="id" value="{$ctx:id.empty}" />
                                 <with-param name="status" value="error" />
                                 <with-param name="message" value="{$ctx:errorMessage}" />
                              </call-template>
                              <loopback />
                           </then>
                           <else>
                              <property name="outletCount" expression="count(//outlets)" />
                              <!-- START: Proceed only if there are any outlets available in Vend. -->
                              <filter source="get-property('outletCount')" regex="0.0">
                                 <then>
                                    <!-- Append a skip message to be sent to the user if there aren't any orders to be processed. -->
                                    <call-template target="responseHandlerTemplate">
                                       <with-param name="activity" value="vend_listOutlets" />
                                       <with-param name="id" value="{$ctx:id.empty}" />
                                       <with-param name="status" value="skipped" />
                                       <with-param name="message" value="There are no outlets in Vend." />
                                    </call-template>
                                    <loopback />
                                 </then>
                                 <else>
                                    <property name="outletIndex" expression="0" scope="operation" />
                                    <!-- FOR EACH Outlet: BEGIN -->
                                    <iterate continueParent="false" id="outlets" expression="//outlets" sequential="true">
                                       <target>
                                          <sequence>
                                             <property name="vend.outletId" expression="//outlets/id/text()" />
                                             <property name="statuses" value="[&quot;CLOSED&quot;]" />
                                             <!-- List all the register sales for the outlet since the given date. -->
                                             <vend.init>
                                                <apiUrl>{$ctx:vend.apiUrl}</apiUrl>
                                                <accessToken>{$ctx:vend.accessToken}</accessToken>
                                             </vend.init>
                                             <vend.listRegisterSales>
                                                <since>{$ctx:vend.salesSince}</since>
                                                <outletId>{$ctx:vend.outletId}</outletId>
                                                <statuses>statuses</statuses>
                                             </vend.listRegisterSales>
                                             <sequence key="removeResponseHeaders" />
                                             <!-- Iterate over the registers and extract the ID of the required register. -->
                                             <script language="js">
                                                <![CDATA[
                                                   var outletId = mc.getProperty('vend.outletId');
                                                   var salesSince = mc.getProperty('vend.salesSince');
                                                   var registerSales = mc.getPayloadJSON().register_sales;
                                                   var giftVoucherPaymentId = '';
                                                   
                                                   if(registerSales.length > 0){
                                                      var customerSaleObject = {};
                                                      
                                                      var firstCustomerId = '';
                                                      var firstCustomerAmount = 0;
                                                      var secondCustomerId = '';
                                                      var secondCustomerAmount = 0;
                                                      var thirdCustomerId = '';
                                                      var thirdCustomerAmount = 0;
                                                      var noOfCustomers = 0;
                                                      
                                                      // Iterate over all the sales and construct a JSON object with customer IDs as key and their total purchase amount as value.
                                                      for(var i=0; i<registerSales.length; i++){
                                                         var customerId = registerSales[i].customer_id;
                                                         var totalPrice = registerSales[i].total_price;
                                                         var customerEmail = registerSales[i].customer.email;
                                                         
                                                         // Consider only the sales which have a customer associated with it.
                                                         if(customerEmail != null && customerEmail != '' && totalPrice > 0){
                                                            if(customerSaleObject.hasOwnProperty(customerId)){
                                                               customerSaleObject[customerId] = customerSaleObject[customerId] + totalPrice;
                                                            } else {
                                                               noOfCustomers++;
                                                               customerSaleObject[customerId] = totalPrice;
                                                            }
                                                            
                                                            // Set the first, second and third customer
                                                            if(customerSaleObject[customerId] > firstCustomerAmount){
                                                               if(firstCustomerId != customerId){
                                                                  thirdCustomerId = secondCustomerId;
                                                                  thirdCustomerAmount = secondCustomerAmount;
                                                                  secondCustomerId = firstCustomerId;
                                                                  secondCustomerAmount = firstCustomerAmount;                                               
                                                                  firstCustomerId = customerId;
                                                               }
                                                               firstCustomerAmount = customerSaleObject[customerId];
                                                            } else if(customerSaleObject[customerId] > secondCustomerAmount){
                                                               if(secondCustomerId != customerId){
                                                                  thirdCustomerId = secondCustomerId;
                                                                  thirdCustomerAmount = secondCustomerAmount;
                                                                  secondCustomerId = customerId;
                                                               }                                                
                                                               secondCustomerAmount = customerSaleObject[customerId];
                                                            } else if(customerSaleObject[customerId] > thirdCustomerAmount){
                                                               thirdCustomerId = customerId;
                                                               thirdCustomerAmount = customerSaleObject[customerId];
                                                            }
                                                            
                                                         }                                       
                                                      }                                                 
                                                      
                                                      mc.setProperty('firstCustomerId', firstCustomerId); 
                                                      mc.setProperty('firstCustomerAmount', firstCustomerAmount); 
                                                      mc.setProperty('secondCustomerId', secondCustomerId); 
                                                      mc.setProperty('secondCustomerAmount', secondCustomerAmount); 
                                                      mc.setProperty('thirdCustomerId', thirdCustomerId); 
                                                      mc.setProperty('thirdCustomerAmount', thirdCustomerAmount); 
                                                      mc.setProperty('vend.noOfCustomers', noOfCustomers);
                                                      
                                                      mc.setPayloadJSON(customerSaleObject);
                                                   }       
                                                ]]>
                                             </script>
                                             <property name="fullProducts" expression="get-property('operation', 'fullProducts')" />
                                             
                                             <!-- START: Proceed to reward the first customer only if the requirements are met. -->
                                             <filter xpath="(get-property('noOfFirstCustomerProducts') > 0) and
                                                            (get-property('firstCustomerAmount') > 0.0) and
                                                            (get-property('firstCustomerAmount') >= get-property('vend.minimumSalesAmount')) and
                                                            (get-property('vend.noOfCustomers') >= get-property('vend.minimumCustomersForFirst'))">
                                                <then>
                                                   <property name="rewardedCustomers" expression="get-property('operation', 'rewardedCustomers') + 1" scope="operation" />
                                                   <call-template target="vend-rewardCustomerWithGiftPack">
                                                      <with-param name="vend.apiUrl" value="{$ctx:vend.apiUrl}" />
                                                      <with-param name="vend.accessToken" value="{$ctx:vend.accessToken}" />
                                                      <with-param name="vend.fullProducts" value="{$ctx:fullProducts}" />
                                                      <with-param name="vend.products" value="{$ctx:vend.productsForFirstCustomer}" />
                                                      <with-param name="vend.customerId" value="{$ctx:firstCustomerId}" />
                                                      <with-param name="vend.paymentTypeId" value="{$ctx:vend.giftVoucherPaymentId}" />
                                                      <with-param name="vend.registerId" value="{$ctx:vend.registerId}" />
                                                      <with-param name="vend.fromName" value="{$ctx:vend.fromName}" />
                                                      <with-param name="vend.fromEmail" value="{$ctx:vend.fromEmail}" />
                                                      <with-param name="vend.salesSince" value="{$ctx:vend.salesSince}" />
                                                      <with-param name="vend.salesAmount" value="{$ctx:firstCustomerAmount}" />
                                                      <with-param name="vend.customerPosition" value="First" />
                                                      <with-param name="nexmo.apiUrl" value="{$ctx:nexmo.apiUrl}" />
                                                      <with-param name="nexmo.apiKey" value="{$ctx:nexmo.apiKey}" />
                                                      <with-param name="nexmo.apiSecret" value="{$ctx:nexmo.apiSecret}" />
                                                      <with-param name="mandrill.apiKey" value="{$ctx:mandrill.apiKey}" />
                                                      <with-param name="mandrill.apiUrl" value="{$ctx:mandrill.apiUrl}" />
                                                      <with-param name="beetrack.apiUrl" value="{$ctx:beetrack.apiUrl}" />
                                                      <with-param name="beetrack.accessToken" value="{$ctx:beetrack.accessToken}" />
                                                      <with-param name="beetrack.vehicleId" value="{$ctx:beetrack.vehicleId}" />
                                                   </call-template>

                                                </then>
                                             </filter>
                                             <!-- END: Proceed to reward the first customer only if the requirements are met. -->
                                             
                                             <!-- START: Proceed to reward the second customer only if the requirements are met. -->
                                             <filter xpath="(get-property('noOfSecondCustomerProducts') > 0) and
                                                            (get-property('secondCustomerAmount') > 0) and
                                                            (get-property('secondCustomerAmount') >= get-property('vend.minimumSalesAmount')) and
                                                            (get-property('vend.noOfCustomers') >= get-property('vend.minimumCustomersForSecond'))">
                                                <then>
                                                   <property name="rewardedCustomers" expression="get-property('operation', 'rewardedCustomers') + 1" scope="operation" />
                                                   <call-template target="vend-rewardCustomerWithGiftPack">
                                                      <with-param name="vend.apiUrl" value="{$ctx:vend.apiUrl}" />
                                                      <with-param name="vend.accessToken" value="{$ctx:vend.accessToken}" />
                                                      <with-param name="vend.fullProducts" value="{$ctx:fullProducts}" />
                                                      <with-param name="vend.products" value="{$ctx:vend.productsForSecondCustomer}" />
                                                      <with-param name="vend.customerId" value="{$ctx:secondCustomerId}" />
                                                      <with-param name="vend.paymentTypeId" value="{$ctx:vend.giftVoucherPaymentId}" />
                                                      <with-param name="vend.registerId" value="{$ctx:vend.registerId}" />
                                                      <with-param name="vend.fromName" value="{$ctx:vend.fromName}" />
                                                      <with-param name="vend.fromEmail" value="{$ctx:vend.fromEmail}" />
                                                      <with-param name="vend.salesSince" value="{$ctx:vend.salesSince}" />
                                                      <with-param name="vend.salesAmount" value="{$ctx:secondCustomerAmount}" />
                                                      <with-param name="vend.customerPosition" value="Second" />
                                                      <with-param name="nexmo.apiUrl" value="{$ctx:nexmo.apiUrl}" />
                                                      <with-param name="nexmo.apiKey" value="{$ctx:nexmo.apiKey}" />
                                                      <with-param name="nexmo.apiSecret" value="{$ctx:nexmo.apiSecret}" />
                                                      <with-param name="mandrill.apiKey" value="{$ctx:mandrill.apiKey}" />
                                                      <with-param name="mandrill.apiUrl" value="{$ctx:mandrill.apiUrl}" />
                                                      <with-param name="beetrack.apiUrl" value="{$ctx:beetrack.apiUrl}" />
                                                      <with-param name="beetrack.accessToken" value="{$ctx:beetrack.accessToken}" />
                                                      <with-param name="beetrack.vehicleId" value="{$ctx:beetrack.vehicleId}" />
                                                   </call-template>
                                                </then>
                                             </filter>
                                             <!-- END: Proceed to reward the second customer only if the requirements are met. -->
                                             
                                             <!-- START: Proceed to reward the third customer only if the requirements are met. -->
                                             <filter xpath="(get-property('noOfThirdCustomerProducts') > 0) and
                                                            (get-property('thirdCustomerAmount') > 0) and
                                                            (get-property('thirdCustomerAmount') >= get-property('vend.minimumSalesAmount')) and
                                                            (get-property('vend.noOfCustomers') >= get-property('vend.minimumCustomersForThird'))">
                                                <then>
                                                   <property name="rewardedCustomers" expression="get-property('operation', 'rewardedCustomers') + 1" scope="operation" />
                                                   <call-template target="vend-rewardCustomerWithGiftPack">
                                                      <with-param name="vend.apiUrl" value="{$ctx:vend.apiUrl}" />
                                                      <with-param name="vend.accessToken" value="{$ctx:vend.accessToken}" />
                                                      <with-param name="vend.fullProducts" value="{$ctx:fullProducts}" />
                                                      <with-param name="vend.products" value="{$ctx:vend.productsForThirdCustomer}" />
                                                      <with-param name="vend.customerId" value="{$ctx:thirdCustomerId}" />
                                                      <with-param name="vend.paymentTypeId" value="{$ctx:vend.giftVoucherPaymentId}" />
                                                      <with-param name="vend.registerId" value="{$ctx:vend.registerId}" />
                                                      <with-param name="vend.fromName" value="{$ctx:vend.fromName}" />
                                                      <with-param name="vend.fromEmail" value="{$ctx:vend.fromEmail}" />
                                                      <with-param name="vend.salesSince" value="{$ctx:vend.salesSince}" />
                                                      <with-param name="vend.salesAmount" value="{$ctx:thirdCustomerAmount}" />
                                                      <with-param name="vend.customerPosition" value="Third" />
                                                      <with-param name="nexmo.apiUrl" value="{$ctx:nexmo.apiUrl}" />
                                                      <with-param name="nexmo.apiKey" value="{$ctx:nexmo.apiKey}" />
                                                      <with-param name="nexmo.apiSecret" value="{$ctx:nexmo.apiSecret}" />
                                                      <with-param name="mandrill.apiKey" value="{$ctx:mandrill.apiKey}" />
                                                      <with-param name="mandrill.apiUrl" value="{$ctx:mandrill.apiUrl}" />
                                                      <with-param name="beetrack.apiUrl" value="{$ctx:beetrack.apiUrl}" />
                                                      <with-param name="beetrack.accessToken" value="{$ctx:beetrack.accessToken}" />
                                                      <with-param name="beetrack.vehicleId" value="{$ctx:beetrack.vehicleId}" />
                                                   </call-template>
                                                </then>
                                             </filter>
                                             <!-- END: Proceed to reward the first customer only if the requirements are met. -->
                                             <property name="outletIndex" expression="get-property('operation', 'outletIndex') + 1" scope="operation" />
                                             <filter xpath="get-property('outletCount') = get-property('operation', 'outletIndex')">
                                                <then>
                                                   <!-- Append a skip message to be sent to the user if there are no new orders to process. -->
                                                   <filter source="get-property('operation', 'rewardedCustomers')" regex="0.0">
                                                      <then>
                                                         <call-template target="responseHandlerTemplate">
                                                            <with-param name="activity" value="vend_discoverPremiumCustomersAndReward" />
                                                            <with-param name="id" value="{$ctx:id.empty}" />
                                                            <with-param name="status" value="skipped" />
                                                            <with-param name="message" value="There aren't any eligible customers to be rewarded." />
                                                         </call-template>
                                                      </then>
                                                   </filter>
                                                   <loopback />
                                                </then>
                                             </filter>
                                          </sequence>
                                       </target>
                                    </iterate>
                                    <!-- FOR EACH Outlet: END -->
                                 </else>
                              </filter>
                              <!-- END: Proceed only if there are any outlets available in Vend. -->
                           </else>
                        </filter>
                        <!-- END: Proceed only if the listOutlets call is successful. -->
                     </then>
                  </filter>
                  <!-- END: Proceed with the remainder of the scenarios once all the gift products are processed. -->
               </sequence>
            </target>
         </iterate>
         <!--FOR EACH Product : END -->
      </inSequence>
      <outSequence>
         <property name="messageType" value="application/json" scope="axis2" />
         <payloadFactory media-type="json">
            <format>
               {
               "Response":{
               "process":"vend_discoverPremiumCustomersAndReward",
               "activityResponse":[$1]
               }
               }
            </format>
            <args>
               <arg expression="get-property('operation', 'responseString')" />
            </args>
         </payloadFactory>
         <send />
      </outSequence>
   </target>
</proxy>
Sample Request for discovering premium customers based on sales, creating a gift pack for them to be sent as a reward, creating a route in Beetrack for the gift pack to be delivered to the customer and notifying the customer about the reward via e-mail and SMS
{
    "vend": {
        "salesSince": "2015-10-01 00:00:00",
        "minimumSalesAmount": 500,
        "registerId": "31eb0866-e756-11e5-fed9-62b2e0643817",
        "fromName": "Yasvini Trolleys",
        "fromEmail": "besafe.abdera@gmail.com",
        "firstCustomer": {
            "minimumCustomers": 2,
            "products": [
                {
                    "id": "31eb0866-e731-11e5-fed9-62b7871ecf8b",
                    "quantity": 1
                },
                {
                    "id": "31eb0866-e731-11e5-fed9-62b73dc52da4",
                    "quantity": 2
                },
                {
                    "id": "31eb0866-e731-11e5-fed9-62b704a2f814",
                    "quantity": 3
                }
            ]
        },
        "secondCustomer": {
            "minimumCustomers": 3,
            "products": [
                {
                    "id": "31eb0866-e731-11e5-fed9-62b7871ecf8b",
                    "quantity": 2
                },
                {
                    "id": "31eb0866-e731-11e5-fed9-62b73dc52da4",
                    "quantity": 2
                }
            ]
        },
        "thirdCustomer": {
            "minimumCustomers": 4,
            "products": [
                {
                    "id": "31eb0866-e731-11e5-fed9-62b7871ecf8b",
                    "quantity": 3
                }
            ]
        }
    },
    "beetrack": {
        "vehicleId": "Toyota 121"
    }
}

Note

 The following are the parameter descriptions:

  • vend.salesSince: Only the sales taken place from the provided date-time would be considered when deciding the premium customers. If the parameter is not provided, it will be defaulted to 30 days prior to the execution of the scenario.
  • vend.fromName: Name of the company/person to be used as the sender name for the e-mails and SMS messages.
  • vend.fromEmail: E-mail of the company/person to be used as the sender e-mail for the notification e-mails.
  • vend.minimumSalesAmount: Minimum amount of sales a customer should have done in order to be eligible for the reward.
  • vend.registerId: The ID of the register which the gift pack would be created in Vend.
  • vend.firstCustomer, vend.secondCustomer, vend.thirdCustomer: Objects with the following properties:
    • minimumCustomers: Number of total customers (who have done sales within the considered duration) required to reward the respective position (1st, 2nd or 3rd).
    • products: Array of product objects in Vend which are to be included in the gift pack for the customer in the respective position (1st, 2nd or 3rd). Each product object has the following properties:
      • id: The ID of the product in Vend (provide a valid ID).
      • quantity: The quantity of the product.
  • beetrack.vehicleId: The ID of the truck used to create the route in Beetrack for the gift pack.