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

Invoice Handling in Printavo

The third use case in the Printavo business scenario is invoice handling. This page describes the relevant tasks and the operations you use in the Printavo connector and the other ESB connectors. It contains the following sections:

Overview

The flow for invoice handling is illustrated in the following diagram. The ESB connectors for FreshBooks will be used to connect to each service.

Retrieving invoices, creating clients and deleting invoices

  1. Retrieve all the orders from the Printavo API using the listOrders operation.
  2. Retrieve the details of the order using the getOrder operation in the Printavo API.
  3. Retrieve the details of the customer to whom the order belongs using the getCustomer operation in the Printavo API.
  4. Check if the client already exists in the FreshBooks API using the listClients operation.
  5. Create the corresponding client and contact in the FreshBooks API using the createClient operation.
  6. Retrieve the details of the client in order to retrieve the contact person ID using the getClient operation in the FreshBooks API.
  7. Create the invoice for the order in the FreshBooks API using the createInvoice operation. 
  8. Delete the order in the Printavo API using the deleteOrder operation.
Printavo operations
FreshBooks operations
Samples
Sample Proxy for retrieving invoices from Printavo which are in the 'Completed' status and creating them in FreshBooks. If the customer of the invoice is not already in FreshBooks, then creating the customer as client. Deleting the invoices in Printavo upon successful creation of them in FreshBooks
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="printavo_retrieveCompletedOrdersAndCreateInvoices" transports="https http" startOnLoad="true" trace="disable">
   <target>
      <inSequence onError="faultHandlerSeq">
         <!-- Printavo Properties -->
         <property name="printavo.apiUrl" value="https://www.printavo.com" />
         <property name="printavo.apiKey" expression="json-eval($.printavo.apiKey)" />
         <!-- FresBooks Properties -->
         <property name="freshbooks.apiUrl" expression="json-eval($.freshbooks.apiUrl)" />
         <property name="freshbooks.authenticationToken" expression="json-eval($.freshbooks.authenticationToken)" />
         <!-- Common Properties -->
         <property name="responseString" value="" scope="operation" />
         <property name="id.empty" value="{}" />
         <!-- List all the orders from Printavo API -->
         <printavo.init>
            <apiUrl>{$ctx:printavo.apiUrl}</apiUrl>
            <apiKey>{$ctx:printavo.apiKey}</apiKey>
         </printavo.init>
         <printavo.listOrders>
            <page>1</page>
            <perPage>1000</perPage>
         </printavo.listOrders>
         <sequence key="removeResponseHeaders" />
         <property name="printavo.totalOrders" expression="json-eval($.meta.total_count)" />
         <!-- START: Proceed only if the listOrders call was successful. -->
         <filter source="boolean(get-property('printavo.totalOrders'))" regex="false">
            <then>
               <!-- Error case: Append a message to be sent to the user. -->
               <property name="errorResponse" expression="json-eval($)" />
               <call-template target="responseHandlerTemplate">
                  <with-param name="activity" value="printavo_listOrders" />
                  <with-param name="id" value="{$ctx:id.empty}" />
                  <with-param name="status" value="Error" />
                  <with-param name="message" value="{$ctx:errorResponse}" />
               </call-template>
               <loopback />
            </then>
            <else>
               <!-- START: Proceed only if there any listOrders to process. -->
               <filter xpath="get-property('printavo.totalOrders') &gt; 0">
                  <then>
                     <property name="noOfOrders" expression="count(//data)" />
                     <property name="orderIndex" expression="0" scope="operation" />
                     <property name="noOfProcessedOrders" expression="0" scope="operation" />
                     <!--FOR EACH Order: BEGIN -->
                     <iterate continueParent="false" id="orders" expression="//data" sequential="false">
                        <target>
                           <sequence>
                              <property name="printavo.orderId" expression="//data/id/text()" />
                              <property name="printavo.orderStatus" expression="//data/orderstatus/name/text()" />
                              <!-- Retrieve the details of the order. -->
                              <printavo.init>
                                 <apiUrl>{$ctx:printavo.apiUrl}</apiUrl>
                                 <apiKey>{$ctx:printavo.apiKey}</apiKey>
                              </printavo.init>
                              <printavo.getOrder>
                                 <orderId>{$ctx:printavo.orderId}</orderId>
                              </printavo.getOrder>
                              <sequence key="removeResponseHeaders" />
                              <property name="printavo.orderId" expression="json-eval($.id)" />
                              <!-- START: Proceed only if the order is not deleted already -->
                              <filter source="boolean(get-property('printavo.orderId'))" regex="true">
                                 <then>
                                    <!-- START: Proceed to process the order only if it is in 'Completed' status -->
                                    <filter xpath="fn:lower-case(get-property('printavo.orderStatus')) = 'completed'">
                                       <then>
                                          <property name="printavo.orderLineItems" expression="json-eval($.lineitems)" />
                                          <property name="printavo.orderCustomerId" expression="json-eval($.customer_id)" />
                                          <property name="printavo.orderPublicUrl" expression="json-eval($.public_url)" />
                                          <property name="printavo.orderDiscount" expression="json-eval($.discount)" />
                                          <property name="printavo.orderProductionNotes" expression="json-eval($.production_notes)" />
                                          <property name="printavo.orderNotes" expression="json-eval($.notes)" />
                                          <property name="printavo.orderCreatedDate" expression="json-eval($.created_at)" />
                                          <property name="printavo.orderFirstName" expression="json-eval($.customer.first_name)" />
                                          <property name="printavo.orderLastName" expression="json-eval($.customer.last_name)" />
                                          <property name="printavo.orderCompany" expression="json-eval($.customer.company)" />
                                          <property name="printavo.orderTaxPercent" expression="json-eval($.sales_tax)" />
                                          <!-- Retrieve the details of the customer to whom the order belongs. -->
                                          <printavo.init>
                                             <apiUrl>{$ctx:printavo.apiUrl}</apiUrl>
                                             <apiKey>{$ctx:printavo.apiKey}</apiKey>
                                          </printavo.init>
                                          <printavo.getCustomer>
                                             <customerId>{$ctx:printavo.orderCustomerId}</customerId>
                                          </printavo.getCustomer>
                                          <sequence key="removeResponseHeaders" />
                                          <property name="printavo.order.customerEmail" expression="json-eval($.email)" />
                                          <property name="printavo.order.customerFirstName" expression="json-eval($.first_name)" />
                                          <property name="printavo.order.customerLastName" expression="json-eval($.last_name)" />
                                          <property name="printavo.order.customerCompany" expression="json-eval($.company)" />
                                          <property name="printavo.order.customerFax" expression="json-eval($.fax)" />
                                          <property name="printavo.order.customerPhone" expression="json-eval($.phone)" />
                                          <property name="printavo.order.customerShippingAddress1" expression="json-eval($.shipping_address.address1)" />
                                          <property name="printavo.order.customerShippingAddress1" expression="json-eval($.shipping_address.address2)" />
                                          <property name="printavo.order.customerShippingCity" expression="json-eval($.shipping_address.city)" />
                                          <property name="printavo.order.customerShippingState" expression="json-eval($.shipping_address.state)" />
                                          <property name="printavo.order.customerShippingCountry" expression="json-eval($.shipping_address.country)" />
                                          <property name="printavo.order.customerShippingZip" expression="json-eval($.shipping_address.zip)" />
                                          <property name="printavo.order.customerBillingAddress1" expression="json-eval($.billing_address.address1)" />
                                          <property name="printavo.order.customerBillingAddress2" expression="json-eval($.billing_address.address2)" />
                                          <property name="printavo.order.customerBillingCity" expression="json-eval($.billing_address.city)" />
                                          <property name="printavo.order.customerBillingState" expression="json-eval($.billing_address.state)" />
                                          <property name="printavo.order.customerBillingCountry" expression="json-eval($.billing_address.country)" />
                                          <property name="printavo.order.customerBillingZip" expression="json-eval($.billing_address.zip)" />
                                          <property name="printavo.order.customerContact" expression="fn:concat('&lt;contact&gt;&lt;username&gt;', get-property('printavo.order.customerFirstName'), '&lt;/username&gt;&lt;first_name&gt;', get-property('printavo.order.customerFirstName'), '&lt;/first_name&gt;&lt;last_name&gt;', get-property('printavo.order.customerLastName'), '&lt;/last_name&gt;&lt;email&gt;', get-property('printavo.order.customerEmail'), '&lt;/email&gt;&lt;phone1&gt;', get-property('printavo.order.customerPhone'), '&lt;/phone1&gt;&lt;/contact&gt;')" />
                                          <!-- START: Proceed only if the getCustomer call was successful -->
                                          <filter source="boolean(get-property('printavo.order.customerEmail'))" regex="false">
                                             <then>
                                                <!-- Error case: Append a message to be sent to the user. -->
                                                <property name="id" expression="fn:concat('printavo_customerId:', get-property('printavo.order.customerId'))" />
                                                <property name="statusCode" expression="$axis2:HTTP_SC" />
                                                <property name="message" expression="fn:concat('API response status code: ', get-property('statusCode'))" />
                                                <call-template target="responseHandlerTemplate">
                                                   <with-param name="activity" value="printavo_getCustomerDetails" />
                                                   <with-param name="id" value="{$ctx:id}" />
                                                   <with-param name="status" value="Error" />
                                                   <with-param name="message" value="{$ctx:message}" />
                                                </call-template>
                                             </then>
                                             <else>
                                                <!-- Removing properties to prevent ambiguity. -->
                                                <property name="uri.var.page" action="remove" />
                                                <property name="uri.var.perPage" action="remove" />
                                                <!-- Verify whether the client already exists in Freshbooks. -->
                                                <freshbooks.init>
                                                   <apiUrl>{$ctx:freshbooks.apiUrl}</apiUrl>
                                                   <authenticationToken>{$ctx:freshbooks.authenticationToken}</authenticationToken>
                                                </freshbooks.init>
                                                <freshbooks.listClients>
                                                   <email>{$ctx:printavo.order.customerEmail}</email>
                                                </freshbooks.listClients>
                                                <sequence key="removeResponseHeaders" />
                                                <property name="noOfMatchingClients" expression="count(//*[local-name()='clients']/*[local-name()='client'])" />
                                                <!-- START: Verify whether the client already exist in Freshbooks and create if not. -->
                                                <filter xpath="get-property('noOfMatchingClients') &gt; 0">
                                                   <then>
                                                      <!-- Take the first contact as the matching contact and store his IDs for later use. -->
                                                      <property name="freshbooks.clientId" expression="//*[local-name()='clients']/*[local-name()='client'][1]/*[local-name()='client_id']/text()" />
                                                      <property name="freshbooks.contactId" expression="//*[local-name()='clients']/*[local-name()='client'][1]/*[local-name()='contacts']/*[local-name()='contact'][1]/*[local-name()='contact_id']/text()" />
                                                   </then>
                                                   <else>
                                                      <!-- Create the corresponding client and contact in Freshbooks. -->
                                                      <freshbooks.init>
                                                         <apiUrl>{$ctx:freshbooks.apiUrl}</apiUrl>
                                                         <authenticationToken>{$ctx:freshbooks.authenticationToken}</authenticationToken>
                                                      </freshbooks.init>
                                                      <freshbooks.createClient>
                                                         <firstName>{$ctx:printavo.order.customerFirstName}</firstName>
                                                         <lastName>{$ctx:printavo.order.customerLastName}</lastName>
                                                         <organization>{$ctx:printavo.order.customerCompany}</organization>
                                                         <email>{$ctx:printavo.order.customerEmail}</email>
                                                         <username>{$ctx:printavo.order.customerFirstName}</username>
                                                         <password>1qaz2wsx@</password>
                                                         <contacts>{$ctx:printavo.order.customerContact}</contacts>
                                                         <workPhone>{$ctx:printavo.order.customerPhone}</workPhone>
                                                         <fax>{$ctx:printavo.order.customerFax}</fax>
                                                         <language>en</language>
                                                         <currencyCode>USD</currencyCode>
                                                         <pStreet1>{$ctx:printavo.order.customerShippingAddress1}</pStreet1>
                                                         <pStreet2>{$ctx:printavo.order.customerShippingAddress2}</pStreet2>
                                                         <pCity>{$ctx:printavo.order.customerShippingCity}</pCity>
                                                         <pState>{$ctx:printavo.order.customerShippingState}</pState>
                                                         <pCountry>{$ctx:printavo.order.customerShippingCountry}</pCountry>
                                                         <pCode>{$ctx:printavo.order.customerShippingZip}</pCode>
                                                         <sStreet1>{$ctx:printavo.order.customerBillingAddress1}</sStreet1>
                                                         <sStreet2>{$ctx:printavo.order.customerBillingAddress2}</sStreet2>
                                                         <sCity>{$ctx:printavo.order.customerBillingCity}</sCity>
                                                         <sState>{$ctx:printavo.order.customerBillingState}</sState>
                                                         <sCountry>{$ctx:printavo.order.customerBillingCountry}</sCountry>
                                                         <sCode>{$ctx:printavo.order.customerBillingZip}</sCode>
                                                      </freshbooks.createClient>
                                                      <sequence key="removeResponseHeaders" />
                                                      <property name="freshbooks.clientId" expression="//*[local-name()='client_id']/text()" />
                                                      <!-- START: Proceed only if the client is successfully created. -->
                                                      <filter source="boolean(get-property('freshbooks.clientId'))" regex="false">
                                                         <then>
                                                            <!-- Error case: Append a message to be sent to the user. -->
                                                            <property name="id" expression="fn:concat('printavo_customerId:', get-property('printavo.order.customerId'))" />
                                                            <property name="errorResponse" expression="//*[local-name()='error']/text()" />
                                                            <call-template target="responseHandlerTemplate">
                                                               <with-param name="activity" value="freshbooks_createClient" />
                                                               <with-param name="id" value="{$ctx:id.empty}" />
                                                               <with-param name="status" value="Error" />
                                                               <with-param name="message" value="{$ctx:errorResponse}" />
                                                            </call-template>
                                                         </then>
                                                         <else>
                                                            <!-- Success case: Append a message to be sent to the user. -->
                                                            <property name="id" expression="fn:concat('printavo_customerId:', get-property('printavo.order.customerId'), 'freshbooks_clientId:', get-property('freshbooks.clientId'))" />
                                                            <call-template target="responseHandlerTemplate">
                                                               <with-param name="activity" value="freshbooks_createClient" />
                                                               <with-param name="id" value="{$ctx:id}" />
                                                               <with-param name="status" value="Success" />
                                                               <with-param name="message" value="Client has been successfully created." />
                                                            </call-template>
                                                            <!-- Retrieve details of the client to get the contact person ID. -->
                                                            <freshbooks.init>
                                                               <apiUrl>{$ctx:freshbooks.apiUrl}</apiUrl>
                                                               <authenticationToken>{$ctx:freshbooks.authenticationToken}</authenticationToken>
                                                            </freshbooks.init>
                                                            <freshbooks.getClient>
                                                               <clientId>{$ctx:freshbooks.clientId}</clientId>
                                                            </freshbooks.getClient>
                                                            <sequence key="removeResponseHeaders" />
                                                            <property name="freshbooks.contactId" expression="//*[local-name()='client']/*[local-name()='contacts']/*[local-name()='contact'][1]/*[local-name()='contact_id']/text()" />
                                                         </else>
                                                      </filter>
                                                      <!-- END: Proceed only if the client is successfully created. -->
                                                   </else>
                                                </filter>
                                                <!-- END: Verify whether the client already exist in Freshbooks and create if not. -->
                                                <!-- START: Proceed to create the invoice if and only if both the clientId and contactId exists. -->
                                                <filter xpath="boolean(get-property('freshbooks.clientId')) and boolean(get-property('freshbooks.contactId'))">
                                                   <then>
                                                      <script language="js">
                                                         <![CDATA[
                                                            // Constructing line items
                                                            var lineItems = mc.getProperty('printavo.orderLineItems');
                                                            var taxPercent = mc.getProperty('printavo.orderTaxPercent');
                                                            if(lineItems != null && lineItems != ''){
                                                               lineItems = eval("(" + lineItems + ")");
                                                               if(lineItems.length > 0){
                                                                  var lines = '';
                                                                  for(var i=0; i<lineItems.length; i++){
                                                                     var tax = '';
                                                                     if(lineItems[i].lineitem.taxable == true || lineItems[i].lineitem.taxable == 'true'){
                                                                        tax = '<tax1_name>Sales Tax</tax1_name><tax1_percent>' + taxPercent + '</tax1_percent>';
                                                                     }
                                                                     lines += '<line><name>' + lineItems[i].lineitem.style_number + '</name><description>' + lineItems[i].lineitem.style_description + '</description><unit_cost>' + lineItems[i].lineitem.unit_cost + '</unit_cost><quantity>' + lineItems[i].lineitem.total_quantities + '</quantity>' + tax + '</line>';
                                                                  }
                                                                  mc.setProperty('freshbooks.lineItems', lines);
                                                               }
                                                            }
                                                            
                                                            // Constructing contacts
                                                            var contactId = mc.getProperty('freshbooks.contactId');
                                                            mc.setProperty('freshbooks.contacts', '<contact><contact_id>' + contactId + '</contact_id></contact>');
                                                            
                                                            // Constructing date
                                                            var orderCreatedDate = mc.getProperty('printavo.orderCreatedDate');
                                                            mc.setProperty('printavo.orderCreatedDate', orderCreatedDate.split('T')[0]);
                                                         ]]>
                                                      </script>
                                                      <!-- Create the invoice for the order. -->
                                                      <freshbooks.init>
                                                         <apiUrl>{$ctx:freshbooks.apiUrl}</apiUrl>
                                                         <authenticationToken>{$ctx:freshbooks.authenticationToken}</authenticationToken>
                                                      </freshbooks.init>
                                                      <freshbooks.createInvoice>
                                                         <returnUri>{$ctx:printavo.orderPublicUrl}</returnUri>
                                                         <terms>{$ctx:printavo.orderProductionNotes}</terms>
                                                         <date>{$ctx:printavo.orderCreatedDate}</date>
                                                         <contacts>{$ctx:freshbooks.contacts}</contacts>
                                                         <organization>{$ctx:printavo.orderCompany}</organization>
                                                         <firstName>{$ctx:printavo.orderFirstName}</firstName>
                                                         <lastName>{$ctx:printavo.orderLastName}</lastName>
                                                         <currencyCode>USD</currencyCode>
                                                         <status>sent</status>
                                                         <number>{$ctx:printavo.orderId}</number>
                                                         <clientId>{$ctx:freshbooks.clientId}</clientId>
                                                         <discount>{$ctx:printavo.orderDiscount}</discount>
                                                         <lines>{$ctx:freshbooks.lineItems}</lines>
                                                         <language>en</language>
                                                         <notes>{$ctx:printavo.orderNotes}</notes>
                                                      </freshbooks.createInvoice>
                                                      <sequence key="removeResponseHeaders" />
                                                      <property name="freshbooks.invoiceId" expression="//*[local-name()='invoice_id']/text()" />
                                                      <!-- START: Proceed to delete the order only if the invoice was created successfully. -->
                                                      <filter source="boolean(get-property('freshbooks.invoiceId'))" regex="false">
                                                         <then>
                                                            <!-- Error case: Append a message to be sent to the user. -->
                                                            <property name="errorResponse" expression="//*[local-name()='error']/text()" />
                                                            <property name="id" expression="fn:concat('printavo_orderId:', get-property('printavo.orderId'))" />
                                                            <call-template target="responseHandlerTemplate">
                                                               <with-param name="activity" value="freshbooks_createInvoice" />
                                                               <with-param name="id" value="{$ctx:id}" />
                                                               <with-param name="status" value="Error" />
                                                               <with-param name="message" value="{$ctx:errorResponse}" />
                                                            </call-template>
                                                         </then>
                                                         <else>
                                                            <!-- Success case: Append a message to be sent to the user. -->
                                                            <property name="id" expression="fn:concat('printavo_orderId:', get-property('printavo.orderId'), ',freshbooks_invoiceId:', get-property('freshbooks.invoiceId'))" />
                                                            <call-template target="responseHandlerTemplate">
                                                               <with-param name="activity" value="freshbooks_createInvoice" />
                                                               <with-param name="id" value="{$ctx:id}" />
                                                               <with-param name="status" value="Success" />
                                                               <with-param name="message" value="Invoice has been successfully created." />
                                                            </call-template>
                                                            <property name="noOfProcessedOrders" expression="get-property('operation', 'noOfProcessedOrders') + 1" scope="operation" />
                                                            <!-- Delete the order in Printavo order which is successfully created in FreshBooks. -->
                                                            <printavo.init>
                                                               <apiUrl>{$ctx:printavo.apiUrl}</apiUrl>
                                                               <apiKey>{$ctx:printavo.apiKey}</apiKey>
                                                            </printavo.init>
                                                            <printavo.deleteOrder>
                                                               <orderId>{$ctx:printavo.orderId}</orderId>
                                                            </printavo.deleteOrder>
                                                         </else>
                                                      </filter>
                                                      <!-- END: Proceed to delete the order only if the invoice was created successfully. -->
                                                   </then>
                                                   <else>
                                                      <!-- Success case: Append a message to be sent to the user. -->
                                                      <property name="id" expression="fn:concat('printavo_orderId:', get-property('printavo.orderId'))" />
                                                      <call-template target="responseHandlerTemplate">
                                                         <with-param name="activity" value="freshbooks_createInvoice" />
                                                         <with-param name="id" value="{$ctx:id}" />
                                                         <with-param name="status" value="Skipped" />
                                                         <with-param name="message" value="Client and/or Customer missing to create the invoice." />
                                                      </call-template>
                                                   </else>
                                                </filter>
                                                <!-- END: Proceed to create the invoice if and only if both the clientId and contactId exists. -->
                                             </else>
                                          </filter>
                                          <!-- END: Proceed only if the getCustomer call was successful -->
                                       </then>
                                    </filter>
                                    <!-- END: Proceed to process the order only if it is in 'Completed' status -->
                                 </then>
                              </filter>
                              <!-- START: Proceed only if the order is not deleted already -->
                              <!--Increment the order Count by 1 -->
                              <property name="orderIndex" expression="get-property('operation', 'orderIndex') + 1" scope="operation" />
                              <!-- Terminate the inSequence and move to outSequence when all the iterations are done. -->
                              <filter xpath="get-property('noOfOrders') = get-property('operation', 'orderIndex')">
                                 <then>
                                    <filter xpath="get-property('operation', 'noOfProcessedOrders') = 0.0">
                                       <then>
                                          <call-template target="responseHandlerTemplate">
                                             <with-param name="activity" value="printavo_retrieveOrders" />
                                             <with-param name="id" value="{$ctx:id.empty}" />
                                             <with-param name="status" value="Skipped" />
                                             <with-param name="message" value="There are no orders in 'Completed' state." />
                                          </call-template>
                                       </then>
                                    </filter>
                                    <loopback />
                                 </then>
                              </filter>
                           </sequence>
                        </target>
                     </iterate>
                     <!--FOR EACH Order - END -->
                  </then>
                  <else>
                     <!-- Skip case: Append a message to be sent to the user. -->
                     <call-template target="responseHandlerTemplate">
                        <with-param name="activity" value="printavo_listOrders" />
                        <with-param name="id" value="{$ctx:id.empty}" />
                        <with-param name="status" value="Skipped" />
                        <with-param name="message" value="There are no orders to process." />
                     </call-template>
                     <loopback />
                  </else>
               </filter>
               <!-- END: Proceed only if there any listOrders to process. -->
            </else>
         </filter>
         <!-- END: Proceed only if the listOrders call was successful -->
      </inSequence>
      <outSequence>
         <payloadFactory media-type="json">
            <format>
               {
                  "Response":{
                     "process":"printavo_retrieveCompletedOrdersAndCreateInvoices",
                     "activityResponse":[$1]
                  }
               }
            </format>
            <args>
               <arg expression="get-property('operation','responseString')" />
            </args>
         </payloadFactory>
         <property name="messageType" value="application/json" scope="axis2" />
         <property name="HTTP_SC" value="200" scope="axis2"/>
         <send />
      </outSequence>
   </target>
</proxy>      
Sample Request for retrieving invoices from Printavo which are in the 'Completed' status and creating them in FreshBooks. If the customer of the invoice is not already in FreshBooks, then creating the customer as client. Deleting the invoices in Printavo upon successful creation of them in FreshBooks
{
	"printavo":{
		"apiKey":"2203fcf231a651b3ed5300641e00878b"
	},
	"freshbooks":{
		"apiUrl":"https://courtycorporation.freshbooks.com",
		"authenticationToken":"55fb3554eab4848312f48cc28baa5e7e"
	}
}   

Note

All parameters are connector specific and self-explanatory.

Invoices/Quotes in Printavo should be in 'Completed' status to be considered in the scenario.

Retrieving expenses and deleting expenses

  1. Retrieve all the available categories in the FreshBooks API using the listCategory operation. 
  2. Retrieve all the expenses from the Printavo API using the listExpenses operation.
  3. Retrieve the details of the expense using the getExpense operation in the Printavo API.
  4. Create the expense in the FreshBooks API using the createExpense operation. 
  5. Delete the expense from the Printavo API using the deleteExpense operation.
Printavo operations
FreshBooks operations
Samples
Sample Proxy for retrieving expenses from Printavo and creating them in FreshBooks, deleting the expenses in Printavo upon successful creation of them in FreshBooks
<?xml version="1.0" encoding="UTF-8"?>
<proxy xmlns="http://ws.apache.org/ns/synapse" name="printavo_recordExpenses" transports="https http" startOnLoad="true" trace="disable">
   <target>
      <inSequence onError="faultHandlerSeq">
         <!-- Printavo Properties -->
         <property name="printavo.apiUrl" value="https://www.printavo.com" />
         <property name="printavo.apiKey" expression="json-eval($.printavo.apiKey)" />
         <!-- FresBooks Properties -->
         <property name="freshbooks.apiUrl" expression="json-eval($.freshbooks.apiUrl)" />
         <property name="freshbooks.authenticationToken" expression="json-eval($.freshbooks.authenticationToken)" />
         <property name="freshbooks.staffId" expression="json-eval($.freshbooks.staffId)" />
         <!-- Common Properties -->
         <property name="responseString" value="" scope="operation" />
         <property name="id.empty" value="{}" />
         <!-- List all the available categories in Freshbooks -->
         <freshbooks.init>
            <apiUrl>{$ctx:freshbooks.apiUrl}</apiUrl>
            <authenticationToken>{$ctx:freshbooks.authenticationToken}</authenticationToken>
         </freshbooks.init>
         <freshbooks.listCategory>
            <page>1</page>
            <perPage>1000</perPage>
         </freshbooks.listCategory>
         <sequence key="removeResponseHeaders" />
         <property name="freshbooks.categoryId" expression="//*[../*[local-name() = 'name']/text() = 'Printavo Expenses' and local-name() = 'category_id']" />
         <!-- List all the expenses from Printavo API -->
         <printavo.init>
            <apiUrl>{$ctx:printavo.apiUrl}</apiUrl>
            <apiKey>{$ctx:printavo.apiKey}</apiKey>
         </printavo.init>
         <printavo.listExpenses>
            <page>1</page>
            <perPage>1000</perPage>
         </printavo.listExpenses>
         <sequence key="removeResponseHeaders" />
         <property name="printavo.totalExpenses" expression="json-eval($.meta.total_count)" />
         <!-- START: Proceed only if the listExpenses call was successful. -->
         <filter source="boolean(get-property('printavo.totalExpenses'))" regex="false">
            <then>
               <!-- Error case: Append a message to be sent to the user. -->
               <property name="errorResponse" expression="json-eval($)" />
               <call-template target="responseHandlerTemplate">
                  <with-param name="activity" value="printavo_listExpenses" />
                  <with-param name="id" value="{$ctx:id.empty}" />
                  <with-param name="status" value="Error" />
                  <with-param name="message" value="{$ctx:errorResponse}" />
               </call-template>
               <loopback />
            </then>
            <else>
               <!-- START: Proceed only if there any expenses to process. -->
               <filter xpath="get-property('printavo.totalExpenses') &gt; 0">
                  <then>
                     <property name="noOfExpenses" expression="count(//data)" />
                     <property name="expenseIndex" expression="0" scope="operation" />
                     <property name="noOfProcessedExpenses" expression="0" scope="operation" />
                     <!--FOR EACH Expense: BEGIN -->
                     <iterate continueParent="false" id="expenses" expression="//data" sequential="false">
                        <target>
                           <sequence>
                              <property name="printavo.expenseId" expression="//data/id/text()" />
                              <property name="printavo.expenseName" expression="//data/name/text()" />
                              <property name="printavo.expenseAmount" expression="//data/amount/text()" />
                              <property name="printavo.expenseTransactionDate" expression="//data/transaction_date/text()" />
                              <!-- Retrieve the details of the expense. -->
                              <printavo.init>
                                 <apiUrl>{$ctx:printavo.apiUrl}</apiUrl>
                                 <apiKey>{$ctx:printavo.apiKey}</apiKey>
                              </printavo.init>
                              <printavo.getExpense>
                                 <expenseId>{$ctx:printavo.expenseId}</expenseId>
                              </printavo.getExpense>
                              <sequence key="removeResponseHeaders" />
                              <property name="printavo.expenseId" expression="json-eval($.id)" />
                              <!-- START: Proceed only if the expense is not deleted -->
                              <filter source="boolean(get-property('printavo.expenseId'))" regex="true">
                                 <then>
                                    <property name="printavo.expenseAmount" expression="fn:substring-after(get-property('printavo.expenseAmount'), '-')" />
                                    <property name="printavo.expenseTransactionDate" expression="fn:substring-before(get-property('printavo.expenseTransactionDate'), 'T')" />
                                    <!-- Create the expense in Freshbooks. -->
                                    <freshbooks.init>
                                       <apiUrl>{$ctx:freshbooks.apiUrl}</apiUrl>
                                       <authenticationToken>{$ctx:freshbooks.authenticationToken}</authenticationToken>
                                    </freshbooks.init>
                                    <freshbooks.createExpense>
                                       <staffId>{$ctx:freshbooks.staffId}</staffId>
                                       <status>1</status>
                                       <vendor>Printavo</vendor>
                                       <categoryId>{$ctx:freshbooks.categoryId}</categoryId>
                                       <date>{$ctx:printavo.expenseTransactionDate}</date>
                                       <amount>{$ctx:printavo.expenseAmount}</amount>
                                       <notes>{$ctx:printavo.expenseName}</notes>
                                    </freshbooks.createExpense>
                                    <sequence key="removeResponseHeaders" />
                                    <property name="freshbooks.expenseId" expression="//*[local-name()='expense_id']/text()" />
                                    <!-- START: Proceed to delete the expense only if it was created successfully in Freshbooks. -->
                                    <filter source="boolean(get-property('freshbooks.expenseId'))" regex="false">
                                       <then>
                                          <!-- Error case: Append a message to be sent to the user. -->
                                          <property name="errorResponse" expression="//*[local-name()='error']/text()" />
                                          <property name="id" expression="fn:concat('printavo_expenseId:', get-property('printavo.expenseId'))" />
                                          <call-template target="responseHandlerTemplate">
                                             <with-param name="activity" value="freshbooks_createExpense" />
                                             <with-param name="id" value="{$ctx:id}" />
                                             <with-param name="status" value="Error" />
                                             <with-param name="message" value="{$ctx:errorResponse}" />
                                          </call-template>
                                       </then>
                                       <else>
                                          <!-- Success case: Append a message to be sent to the user. -->
                                          <property name="id" expression="fn:concat('printavo_expenseId:', get-property('printavo.expenseId'), ',freshbooks_expenseId:', get-property('freshbooks.expenseId'))" />
                                          <call-template target="responseHandlerTemplate">
                                             <with-param name="activity" value="freshbooks_createExpense" />
                                             <with-param name="id" value="{$ctx:id}" />
                                             <with-param name="status" value="Success" />
                                             <with-param name="message" value="Expense has been successfully created." />
                                          </call-template>
                                          <property name="noOfProcessedExpenses" expression="get-property('operation', 'noOfProcessedExpenses') + 1" scope="operation" />
                                          <!-- Delete the expense in Printavo expense which is successfully created in FreshBooks. -->
                                          <printavo.init>
                                             <apiUrl>{$ctx:printavo.apiUrl}</apiUrl>
                                             <apiKey>{$ctx:printavo.apiKey}</apiKey>
                                          </printavo.init>
                                          <printavo.deleteExpense>
                                             <expenseId>{$ctx:printavo.expenseId}</expenseId>
                                          </printavo.deleteExpense>
                                          <sequence key="removeResponseHeaders" />
                                          <property name="printavo.deletedExpenseId" expression="json-eval($.id)" />
                                          <!-- START: Append an error message to user only if the deletion fails -->
                                          <filter source="boolean(get-property('printavo.deletedExpenseId'))" regex="false">
                                             <then>
                                                <property name="id" expression="fn:concat('printavo_expenseId:', get-property('printavo.expenseId'))" />
                                                <call-template target="responseHandlerTemplate">
                                                   <with-param name="activity" value="printavo_deleteExpense" />
                                                   <with-param name="id" value="{$ctx:id}" />
                                                   <with-param name="status" value="Error" />
                                                   <with-param name="message" value="Unknown error occured while deleting the expense." />
                                                </call-template>
                                             </then>
                                          </filter>
                                          <!-- END: Append an error message to user only if the deletion fails -->
                                       </else>
                                    </filter>
                                    <!-- END: Proceed to delete the expense only if it was created successfully in Freshbooks. -->
                                 </then>
                              </filter>
                              <!-- START: Proceed only if the expense is not deleted -->
                              <!--Increment the order Count by 1 -->
                              <property name="expenseIndex" expression="get-property('operation', 'expenseIndex') + 1" scope="operation" />
                              <!-- Terminate the inSequence and move to outSequence when all the iterations are done. -->
                              <filter xpath="get-property('noOfExpenses') = get-property('operation', 'expenseIndex')">
                                 <then>
                                    <filter xpath="get-property('operation', 'noOfProcessedExpenses') = 0.0">
                                       <then>
                                          <call-template target="responseHandlerTemplate">
                                             <with-param name="activity" value="printavo_retrieveExpenses" />
                                             <with-param name="id" value="{$ctx:id.empty}" />
                                             <with-param name="status" value="Skipped" />
                                             <with-param name="message" value="There are no unprocessed expenses in the account." />
                                          </call-template>
                                       </then>
                                    </filter>
                                    <loopback />
                                 </then>
                              </filter>
                           </sequence>
                        </target>
                     </iterate>
                     <!--FOR EACH Expense - END -->
                  </then>
                  <else>
                     <!-- Skip case: Append a message to be sent to the user. -->
                     <call-template target="responseHandlerTemplate">
                        <with-param name="activity" value="printavo_listExpenses" />
                        <with-param name="id" value="{$ctx:id.empty}" />
                        <with-param name="status" value="Skipped" />
                        <with-param name="message" value="There are no expenses to process." />
                     </call-template>
                     <loopback />
                  </else>
               </filter>
               <!-- END: Proceed only if there any expenses to process. -->
            </else>
         </filter>
         <!-- END: Proceed only if the listExpenses call was successful -->
      </inSequence>
      <outSequence>
         <payloadFactory media-type="json">
            <format>
               {
                  "Response":{
                     "process":"printavo_recordExpenses",
                     "activityResponse":[$1]
                  }
               }
            </format>
            <args>
               <arg expression="get-property('operation','responseString')" />
            </args>
         </payloadFactory>
         <property name="messageType" value="application/json" scope="axis2" />
         <property name="HTTP_SC" value="200" scope="axis2"/>
         <send />
      </outSequence>
   </target>
</proxy>       
Sample Request for retrieving expenses from Printavo and creating them in FreshBooks, deleting the expenses in Printavo upon successful creation of them in FreshBooks
{
	"printavo":{
		"apiKey":"2203fcf231a651b3ed5300641e00878b"
	},
	"freshbooks":{
		"apiUrl":"https://courtycorporation.freshbooks.com",
		"authenticationToken":"55fb3554eab4848312f48cc28baa5e7e",
      "staffId":1
	}
}      

Note

 The following are the parameter descriptions:

  • freshbooks.staffId: The ID of the staff in FreshBooks to whom the expense would be associated. Provide a valid staff ID.

All other parameters are specific and self-explanatory.

A category for expenses called 'Printavo Expenses' should be created in the FreshBooks account.