Lightning Data Service

In this blog post, we are going to see Lightning data service. With the New Lightning Data services, you can able to perform load, create, edit, or delete a record in your component without requiring Apex code. If you think on a high level, lightning Data services are sort of standard controllers for lighting. Another great advantage too with the Lightning Data services is your application will be more on client side app rather than to be server side apps. That’s so cool!  You can implement the Lighting data services by using force:recordData tag.

Let’s take the Quick look:-
Loading Record or Preview:-

To load the data with force:recordData tag, specify the ID of the record to be loaded, a list of fields, and the attribute to which to assign the loaded record. Or you can specify the layout Type so that all field on the layout will be loaded. If you specify the fields it will display on those filed and if you specify the Layout it will display the all the fields in the layout. Here is the example to show the Account Layout

</pre>
<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,lightning:actionOverride" access="global" >

<aura:attribute name="recordId" type="String" />
<aura:attribute name="recorddetails" type="Opportunity" />

<force:recordData recordId="{!v.recordId}"
targetRecord="{!v.recorddetails}"
layoutType="FULL"
fields="Name,Phone,type,Industry"/>


</aura:component>
<pre>

 

By default, force:recordData is not included any UI render. You need to manually include by using outputText or other ways. force:recordData component will provide following methods
getNewRecord: Loads a record template and sets it to force:recordPreview’s targetRecord attribute, including predefined values for the entity and record type.
reloadRecord: Performs the same load function as on init using the current configuration values (recordId, layoutType, mode, and others).
saveRecord: Saves the record.
deleteRecord: Deletes the record.

Editing Record / Saving Record
Now if you see the above code, it’s just display data . not let us modify the code to perform the data edit. Remember you are going to use the lighting component controller to save the data in this case, not apex code. That’s the advantage of the Lightning Data services. See the below code 

<pre><aura:component implements="flexipage:availableForRecordHome,force:hasRecordId"> 
 
 <aura:attribute name="record" type="Object" />
 <aura:attribute name="editRecord" type="Account" />
 
 <force:recordData aura:id="editRec"
 layoutType="FULL"
 recordId="{!v.recordId}"
 targetRecord="{!v.record}"
 targetFields="{!v.editRecord}"
 mode="EDIT" />
 
 <lightning:input aura:id="recordName" name="Name" label="Name"
 value="{!v.editRecord.Name}" required="true"/>
 <lightning:input aura:id="phone" Name="Phone" label="Phone"
 value="{!v.editRecord.CloseDate}" type="phone"/>
 
 <lightning:input aura:id="Type" Name="Type" label="Type"
 value="{!v.editRecord.Amount}" type="number"/>
 
 <lightning:button label="Save Record" onclick="{!c.handleSave}"
 variant="brand" class="slds-m-top--medium"/>
</aura:component>
</pre>

If You see now the data is handling the controller as shown below.

({
    handleSave: function(component, event, helper) {
        component.find("editRec").saveRecord($A.getCallback(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                console.log("Save completed successfully.");
            }
        }));}
})

Your Component controller calls saveRecord() method. The saveRecord() method takes a single callback function, SaveRecordResult, as its only parameter. SaveRecordResult includes a state attribute that tells you whether the save was successful, along with other information you can use to handle the result of the operation.

Creating Records:-
So for we have seen the code to Edit and Preview the data. To create a record using Lightning Data Service, declare force:recordData without assigning a recordId. Next, load a record template by calling the getNewRecord function on force:recordData. Finally, apply values to the new record, and save the record by calling the saveRecord function on force:recordData. Here is the below Component.


<aura:component implements="force:appHostable,flexipage:availableForAllPageTypes,flexipage:availableForRecordHome,force:hasRecordId,lightning:actionOverride" access="global" >

<aura:attribute name="newAcc" type="Object" />
<aura:attribute name="newAccIns" type="Account" />
<force:recordData aura:id="accCreate"
layoutType="FULL"
targetRecord="{!v.newAcc}"
targetFields="{!v.newAccIns}"
/>

<aura:handler name="init" value="{!this}" action="{!c.doInit}"/>

	<lightning:input aura:id="newName" name="Name" label="Name"
value="{!v.newAccIns.Name}" required="true"/>
	<lightning:button label="Cancel" onclick="{!c.handleCancel}" class="slds-m-top--medium" />
	<lightning:button label="Save " onclick="{!c.handleSave}"
variant="brand" class="slds-m-top--medium"/>


</aura:component>

Here is the controller which calls getNewRecord() method on the initialization of component. Once you click on the save that invoke the saveRecord().

({
    doInit: function(component, event, helper) {
        component.find("accCreate").getNewRecord(
            "Account", // sObject type (entityApiName)
            null, // recordTypeId
            false // skip cache?

        );
    },

    handleSave: function(component, event, helper) {
        component.find("accCreate").saveRecord(function(saveResult) {
            if (saveResult.state === "SUCCESS" || saveResult.state === "DRAFT") {
                // Success! Prepare a toast UI message
                var resultsToast = $A.get("e.force:showToast");
                resultsToast.setParams({
                    "title": "Account  Saved",
                    "message": "The new Account  was created."
                });

                // Update the UI: close panel, show toast, refresh account page
                $A.get("e.force:closeQuickAction").fire();
                resultsToast.fire();

                // Reload the view so components not using force:recordData
                // are updated
                $A.get("e.force:refreshView").fire();
            }

        });
    },

    handleCancel: function(component, event, helper) {
        $A.get("e.force:closeQuickAction").fire();
    },
})

Deleting Record:-
To perform the delete operation, call deleteRecord on the force:recordData component from the appropriate controller action handler. deleteRecord takes one argument, a callback function to be invoked when the operation completes. This callback function receives a SaveRecordResult as its only parameter. SaveRecordResult includes a state attribute that indicates success or error and other details you can use to handle the result of the operation.Here is the code.

<aura:component implements="flexipage:availableForRecordHome,force:hasRecordId"><force:recordData aura:id="recDel"
recordId="{!v.recordId}"
fields="Id"
/>
<div class="slds-form-element">
	<lightning:button
label="Delete Record"
onclick="{!c.handleDeleteRecord}"
variant="brand" />
</div>
</aura:component>

In the component’s JavaScript controller, call the deleteRecord() method.
deleteRecord() method takes a similar callback function as the saveRecord()


({
handleDeleteRecord: function(component, event, helper) {
component.find("recordHandler").deleteRecord($A.getCallback(function(deleteResult) {
if (deleteResult.state === "SUCCESS" || deleteResult.state === "DRAFT") {
console.log("Record is deleted.");
}

}));
}
})

Here is the github url for complete code

https://github.com/rajamohanvakati/Lightning-Data-Services

 

 

 

 

Node JS Streaming API examples

In this blog, I am going to explain the how to test the node js application with Salesforce Streaming API. Here I am going to use the nforce, express, and socket.io along with ejs views. Please refer this link to understand the streaming API .Salesforce Streaming API

Step1: – I am assuming you already created a push topic in Salesforce as per the above link.

Step 2: Create a Connect App for authentication from App menu as shown below

Capture

Step 3: – Clone the Complete Repository from the git hub. here is the link
https://github.com/rajamohanvakati/Node-Js-Steaming-
Open auth.js file from Auth folder and update the details as shown below .

exports.PORT = 3001;
exports.DEBUG = true
exports.ENVIRONMENT = ‘production’;
exports.CALLBACK_URL = ‘http://localhost:3001&#8217;;
exports.PUSH_TOPIC = ‘OpportunityChannel’;
exports.CLIENT_ID =””;
exports.CLIENT_SECRET = “”;
exports.USERNAME = “”;
exports.PASSWORD = “”

Here is the index.js file that contains the logic to connect the Salesforce push topic and establish the socket connection. Once Streaming API topic is receiving any message then socket.io emit that message to index.ejs where we are showing the push notification. This is completed index.js

var express = require('express');
var nforce = require('nforce');
var path = require('path');
var app = express();

var server = require('http').Server(app);
// attach socket.io and listen
var io = require('socket.io')(server);

var config = require('./Auth/auth.js');
var sfConn = nforce.createConnection({
  clientId: config.CLIENT_ID, //Connected app clientId
  clientSecret: config.CLIENT_SECRET, // Connected app clientSecret
  redirectUri: config.CALLBACK_URL + '/oauth/_callback', // call back URL
  environment: config.ENVIRONMENT // optional, sandbox or production, production default
});
sfConn.authenticate({
  username: config.USERNAME, //  salesforce User name
  password: config.PASSWORD // Salesforce password
}, function(error, oauth) {
  if (error) return console.log(error);
  if (!error) {
    console.log('*** Successfully connected to Salesforce ***');
  }
  var streamingConnect = sfConn.stream({
    topic: config.PUSH_TOPIC,
    oauth: oauth
  });
  streamingConnect.on('connect', function() {
    console.log('Connected to pushtopic: ' + config.PUSH_TOPIC);
  });
  streamingConnect.on('error', function(error) {
    console.log('Error received from pushtopic: ' + error);
  });
  streamingConnect.on('data', function(data) {
    console.log('Received the following from pushtopic:');
    console.log(data);
    io.sockets.emit('records', data);
    console.log('after sent to emilt');

  });
});
app.set('port', process.env.PORT || 3001);
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');
app.get('/', function(req, res) {
  res.render('index');

})

server.listen(app.get('port'), function() {
  console.log('Express server listening on port %d in %s mode', app.get(
    'port'), app.get('env'));
});

In index.js once your receive the notification, you can broadcasting it by using socket emit method as show below

streamingConnect.on('data', function(data) {
    console.log('Received the following from pushtopic:');
    console.log(data);
   &lt;strong&gt; io.sockets.emit('records', data);&lt;/strong&gt;
    console.log('after sent to emilt');

  });

The emitted message is reviving in views as show below


var socket = io(url);
socket.on('records', function (data) {
console.log(data);
console.log(data.sobject );
console.log(data.sobject.Id );

//var results = JSON.parse(data.sobject);
var streamList = $('ul.streams');

streamList.prepend('&amp;amp;lt;br/&amp;amp;gt; &amp;amp;lt;li&amp;amp;gt;' +
  data.sobject.Name + ' : ' + data.sobject.StageName +
   data.sobject.Amount + ': ' + data.sobject.ExpectedRevenue +'&amp;amp;lt;/li&amp;amp;gt;');
});

Now you can run the app by simply two commands

npm install

node index.js

after that you can open “http://localhost:3001/ ” in the browser you will see the notification on the browser

Capture

Step 4: Pushing it to Heroku
you can push this app to Heroku with simple steps
Heroku login
Heroku create
git push heroku master
heroku ps:scale web=1
heroku open

 

 

 

 

 

 

 

 

 

 

 

 

Salesforce DocuSign Integration

In this blog, I am going to explain how to use DocuSign’s API in Salesforce. DocuSign is having support for both the SOAP and REST API support. This article is the target for DocuSign SOAP API only.
What you are going to learn in this article are.
 How to use DocuSign API
How to create a template for DocuSign signature requests / e-sign
How to integrate it with APEX

Pre Requisitions:

         DocuSign Account – Register from  (https://www.docusign.com)

         DocuSign For Salesforce Package installed and configured.

Let’s get started.

Step 1:  Download DocuSign WSDL.

        Go to the below URL and download the DocuSign WSDL file.

       https://www.docusign.net/api/3.0/schema/dsapi.wsdl

 Step 2: Generated Apex Class from WSDL.

        In order to create the Apex class from DocuSign WSDL, I am utilizing Salesforce WSDL to apex class features.

        Go to Setup – > Develop – > Apex Classes – >generate from WSDL -> Chose the downloaded DocuSign WSDL

Step 3: Remote Site Settings

        Add below URL to remote Site settings. Remote site settings URL will differ from the DocuSign Sandbox vs. DocuSign Production 

          https://www.docusign.net

Step 4: Generate template for your e-signature.

        You can able to use any of static documents or visual force pages for DocuSign e-sign documents. 

        Now you are going to create a visual force page pdf that needs to send for DocuSign signature.

The below code is the key are in a visual force page which used to capture the recipient signature and print name and date.

 

           

By Completeing DocuSign, You are agreed  terms and Conditions .

           

Customer Name: (Please print) cstnamtag

       

Signed: Signaturetag

       

Date: signdatetag

 

On the above code, three id tags are there namely cstnamtag , Signaturetag and signdatetag .We will use these tags to place signature and Date and print name on DocuSign e-copy document.  

Step 5: triggering the e- signature.

   Here is the sample button that used to send the DocuSign to the end user.

On Click of Send DocuSign, button end user will receive an email with attachment need to be signed. 

Step 6: Docu Sign Terminology and Code Walkthrough

  Some common terms you need to understand. 

Document

    A digital file that contains content to be reviewed and/or signed or initialed by one or more recipients. DocuSign accepts almost all document types – for example .pdf, .docx, .rtf, .png – and you can store multiple documents in a single envelope.

Envelope

      An envelope is a container or “package” that is used to send documents to recipients and manage transactions. Envelopes have statuses (i.e. sent, delivered, completed, voided) and typically contain documents, recipients, and tabs.  

Recipient

       Someone who receives an envelope and, depending on the settings, can sign the documents or add information where indicated by tabs. Recipients do not need a DocuSign account to sign or participate in transactions, and there are seven (7) different recipient types available in the platform. When you embed document signing into your UI your recipients are known as embedded recipients; users who sign through the DocuSign website are known as remote recipients.

Tab

        A DocuSign Tab – also called a Field or Tag – are used in several ways. First, they are used to indicate to a recipient where a signature or initials are required.

Second, tabs can be used to show data or information to recipients, such as dates, company names, titles, etc.

Third, tabs may be used as editable information fields where signers can add data to a document.

Code Walkthrough. 

 Below piece shows BLOB that will send as Document through DocuSign 

   Blob SignDocument= Blob.valueOf(' '); 
        PageReference pr = new PageReference('/apex/DocuSignDynamicGeneration') ;
        SignDocument = pr.getContentAsPDF();

Below piece of code shows the Authentication for DocuSign API. 

   DocuSignAPI.APIServiceSoap dsApiSend = new DocuSignAPI.APIServiceSoap();
        dsApiSend.endpoint_x = webServiceUrl;
        dsApiSend.timeout_x=120000;

        String auth = '&amp;amp;amp;amp;amp;lt;DocuSignCredentials&amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;lt;Username&amp;amp;amp;amp;amp;gt;'+ userId 
            +'&amp;amp;amp;amp;amp;lt;/Username&amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;lt;Password&amp;amp;amp;amp;amp;gt;' + password 
            + '&amp;amp;amp;amp;amp;lt;/Password&amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;lt;IntegratorKey&amp;amp;amp;amp;amp;gt;' + integratorsKey 
            + '&amp;amp;amp;amp;amp;lt;/IntegratorKey&amp;amp;amp;amp;amp;gt;&amp;amp;amp;amp;amp;lt;/DocuSignCredentials&amp;amp;amp;amp;amp;gt;';

        dsApiSend.inputHttpHeaders_x = new Map&amp;amp;amp;amp;amp;lt;String, String&amp;amp;amp;amp;amp;gt;();
        dsApiSend.inputHttpHeaders_x.put('X-DocuSign-Authentication',auth);

Below piece of code shows  how to create an Envelope and Document for doucSIgn 


        DocuSignAPI.Envelope envelope = new DocuSignAPI.Envelope();
        envelope.Subject    = 'DocuSign from Raj'; 
        envelope.EmailBlurb = 'Review review the documnet and sign ';
        envelope.AccountId  = accountId;

        DocuSignAPI.Document document = new DocuSignAPI.Document();
        document.ID                     = 1;
        document.pdfBytes               = EncodingUtil.base64Encode(SignDocument);
        document.Name                   = 'Contract infomration';
        document.FileExtension          = '.pdf';
        envelope.Documents              = new DocuSignAPI.ArrayOfDocument();
        envelope.Documents.Document     = new DocuSignAPI.Document[1];
        envelope.Documents.Document[0]  = document;

Below piece of code shows the how to set recipient details 


        DocuSignAPI.Recipient recipient = new DocuSignAPI.Recipient();
        recipient.ID            = 1;
        recipient.Type_x        = 'Signer';
        recipient.RoutingOrder  = 1;
        recipient.Email         = 'aaaaaaaa@gmail.com';
        recipient.UserName      = 'aaaaaaaaaaaaaaaa';
        recipient.SignerName    = 'Raj ';

        DocuSignAPI.Recipient recipient1 = new DocuSignAPI.Recipient();
        recipient1.ID = 2;
        recipient1.Type_x = 'CarbonCopy';
        recipient1.RoutingOrder = 1;
        recipient1.UserName = 'mohan'; 
        recipient1.Email =  'aaaaaaaaaaaaaaa.v@gmail.com'; 

        DocuSignAPI.Recipient recipient2 = new DocuSignAPI.Recipient();
        recipient2.ID = 3;
        recipient2.Type_x = 'CarbonCopy';
        recipient2.RoutingOrder = 1;
        recipient2.UserName = 'Raj '; 
        recipient2.Email =  'aaaaaaaaaaaaaaaa@outloo.com'; 

Below code shows how to place the signed and Print name and date of DocuSign Documents that need to be signed by the user .


        DocuSignAPI.Tab tab1                = new DocuSignAPI.Tab();
        tab1.Type_x                         = 'SignHere';
        tab1.RecipientID                    = 1;
        tab1.DocumentID                     = 1;
        tab1.AnchorTabItem                  = new DocuSignAPI.AnchorTab();
        tab1.AnchorTabItem.AnchorTabString  = 'Signaturetag';

        DocuSignAPI.Tab tab2                = new DocuSignAPI.Tab();
        tab2.Type_x                         = 'DateSigned';
        tab2.RecipientID                    = 1;
        tab2.DocumentID                     = 1;
        tab2.AnchorTabItem                  = new DocuSignAPI.AnchorTab();
        tab2.AnchorTabItem.AnchorTabString  = 'signdatetag';

        DocuSignAPI.Tab tab4                = new DocuSignAPI.Tab();
        tab4.Type_x                         = 'FullName';
        tab4.RecipientID                    = 1;
        tab4.DocumentID                     = 1;
        tab4.AnchorTabItem                  = new DocuSignAPI.AnchorTab();
        tab4.AnchorTabItem.AnchorTabString  = 'cstnamtag';

finally creating envelop that will trigger an email to user and store in DocuSign Magamed Package object “dsfs__DocuSign_Status__c” to track the Status like Send, Completed and Voided or decline etc. 


        DocuSignAPI.EnvelopeStatus EnvStatus = dsApiSend.CreateAndSendEnvelope(envelope);
        String envelopeId = EnvStatus.EnvelopeID;

        dsfs__DocuSign_Status__c DocStatus      = new dsfs__DocuSign_Status__c();
        DocStatus.dsfs__DocuSign_Envelope_ID__c = envelopeId;
        DocStatus.dsfs__Sender__c               = userinfo.getusername();
        DocStatus.dsfs__Sender_Email__c         = userinfo.getuseremail();
        DocStatus.dsfs__Subject__c              = envelope.Subject;
        DocStatus.dsfs__Envelope_Status__c  = EnvStatus.status;
        insert DocStatus;

Step 7: tracking status for DocuSign.

Once DocuSign is sent to the User, you can track the DocuSign status on dsfs__DocuSign_Status__c t.

Complete code URL.

https://github.com/rajamohanvakati/DocuSign

 

 

 

 

Salesforce Apex Convert Lead

In many of the business cases, you may want control lead conversion process through apex trigger or your may need to build your own lead conversion process . in this post, we are going to see how to control the lead conversion from the apex trigger.

What happens when the lead is converted?

  • A contact, account, and opportunity are created and populated with the lead’s data
    The lead field “Converted” is changed from False to True.
  • The data within standard lead fields is automatically transferred to the contact, account, and/or opportunity. For Custom Field use Lead mapping
  • In general on lead conversion, if you wanted to perform any custom logics like then you will go for apex lead conversion.
    Here are some of the use cases.
    1.Checking Account Industry and SIC mapping against your company mapping
    2.On lead Conversion, if you wanted to auto subscribe specific user the record for chatter feed
    3. Sending new or updated account information to ERP or etc.
    Here is the simple job that will convert leads. You can schedule this class to perform the automatic lead conversion
  global class LeadConversionJob implements Schedulable {
    global void execute(SchedulableContext sc){
        List&amp;amp;lt;Lead&amp;amp;gt; leads = [Select Id , Name,Company  from lead where LeadSource='Web' ];

        List&amp;amp;lt;Database.LeadConvert&amp;amp;gt; lcList = new List&amp;amp;lt;Database.LeadConvert&amp;amp;gt;();
        for(Lead l :leads){
            Database.LeadConvert lc = new Database.LeadConvert();
            lc.setLeadId(l.id);
            lc.ConvertedStatus = 'Closed - Converted';
            lcList.add(lc);
        }
        List&amp;amp;lt;Database.LeadConvertResult&amp;amp;gt; lcr = Database.convertLead(lcList);      
        for(Database.LeadConvertResult lcrRes : lcr){
            if(lcrRes.isSuccess()){

            }else{
                //error handling here 
            }

        }

    }

}

If you would like to perform some of the operations on after lead is conversion or to perform some of the business requirements, you write apex trigger as shown below.

Apex Trigger:-

 trigger LeadConversion on Lead (after update) {

    LeadConversionHandler.convertLead(Trigger.newMap , Trigger.oldMap);

}

Apex Class

public class LeadConversionHandler {

    public static void convertLead(Map&lt;Id, Lead&gt; newLead , Map&lt;Id ,Lead&gt; oldLead){
        for(Id idNew :newLead.keySet()){
            If(newLead.get(idNew).isConverted== true &amp;&amp;  oldLead.get(idNew).isConverted== false){
                If(newLead.get(idNew).ConvertedAccountId!=null){
                    // Use your logics here
                    Account a = [Select a.Id, a.Description From Account a Where a.Id = :newLead.get(idNew).ConvertedAccountId];

                }     
                If(newLead.get(idNew).ConvertedContactId!=null){
                    // Use your logics here 
                    Contact c = [Select c.Id, c.Description, c.Name From Contact c Where c.Id = :newLead.get(idNew).ConvertedContactId];
                }
                If(newLead.get(idNew).ConvertedOpportunityId!=null){
                    // use your logics here 
                    Opportunity opp = [Select o.Id, o.Description from Opportunity o Where o.Id = :newLead.get(idNew).ConvertedOpportunityId];

                }
            } 

        }

    }

}