Monday, 23 July 2018

Get RecordType Name inside Trigger

When you are going through loop in a trigger you don’t have access to Record Type name like RecordType.Name, you can only access Id as RecordTypeId
1trigger TriggerName on Account (after insert, after update) {
2    for (Account o : Trigger.new) {
3    type = o.RecordTypeId;
4}
RecordTypeId works, because that’s the actual field on Account (a lookup to RecordType). And as with all lookup fields in a trigger, to get the related value, you need to query for it.
However, you can also use before your loop
1Map<ID, Schema.RecordTypeInfo> rtMap = Schema.SObjectType.Account.getRecordTypeInfosById();
and then inside your loop:
1type = rtMap.get(o.RecordTypeId).getName();

Saturday, 21 July 2018

Create Account record using REST and Workbench

Method: Post
URL : /services/data/v36.0/sobjects/account
BODY : {
  "Name" : "Blackbeards Grog Emporium",
  "description" : "The finest grog in the seven seas."
}




Batch class with Database state full

global class UpdateContactAddresses implements
    Database.Batchable<sObject>, Database.Stateful {
   
    // instance member to retain state across transactions
    global Integer recordsProcessed = 0;
    global Database.QueryLocator start(Database.BatchableContext bc) {
        return Database.getQueryLocator(
            'SELECT ID, BillingStreet, BillingCity, BillingState, ' +
            'BillingPostalCode, (SELECT ID, MailingStreet, MailingCity, ' +
            'MailingState, MailingPostalCode FROM Contacts) FROM Account ' +
            'Where BillingCountry = \'USA\''
        );
    }
    global void execute(Database.BatchableContext bc, List<Account> scope){
        // process each batch of records
        List<Contact> contacts = new List<Contact>();
        for (Account account : scope) {
            for (Contact contact : account.contacts) {
                contact.MailingStreet = account.BillingStreet;
                contact.MailingCity = account.BillingCity;
                contact.MailingState = account.BillingState;
                contact.MailingPostalCode = account.BillingPostalCode;
                // add contact to list to be updated
                contacts.add(contact);
                // increment the instance member counter
                recordsProcessed = recordsProcessed + 1;
            }
        }
        update contacts;
    }   
    global void finish(Database.BatchableContext bc){
        System.debug(recordsProcessed + ' records processed. Shazam!');
        AsyncApexJob job = [SELECT Id, Status, NumberOfErrors,
            JobItemsProcessed,
            TotalJobItems, CreatedBy.Email
            FROM AsyncApexJob
            WHERE Id = :bc.getJobId()];
        // call some utility to send email
        EmailUtils.sendMessage(a, recordsProcessed);
    }   
}



Test class:-

@isTest
private class UpdateContactAddressesTest {
    @testSetup
    static void setup() {
        List<Account> accounts = new List<Account>();
        List<Contact> contacts = new List<Contact>();
        // insert 10 accounts
        for (Integer i=0;i<10;i++) {
            accounts.add(new Account(name='Account '+i,
                billingcity='New York', billingcountry='USA'));
        }
        insert accounts;
        // find the account just inserted. add contact for each
        for (Account account : [select id from account]) {
            contacts.add(new Contact(firstname='first',
                lastname='last', accountId=account.id));
        }
        insert contacts;
    }
    static testmethod void test() {       
        Test.startTest();
        UpdateContactAddresses uca = new UpdateContactAddresses();
        Id batchId = Database.executeBatch(uca);
        Test.stopTest();
        // after the testing stops, assert records were updated properly
        System.assertEquals(10, [select count() from contact where MailingCity = 'New York']);
    }
   
}

Thursday, 5 July 2018

Using state in Batch Apex

Each execution of batch Apex job is considered a discrete transaction.
For example, a batch Apex job that contains 1,000 records and is executed without the optional scope parameter is considered five transactions of 200 records each.
If you specify Database.Stateful in the class definition, you can maintain state across these transactions. When using Database.Stateful, only instance member variables retain their values between transactions. Static member variables don’t retain their values and are reset between transactions. Maintaining state is useful for counting or summarizing records as they’re processed. For example, suppose your job processed opportunity records. You could define a method in execute to aggregate totals of the opportunity amounts as they were processed.
If you don’t specify Database.Stateful, all static and instance member variables are set back to their original values.
The following example summarizes a custom field total__c as the records are processed.

global class SummarizeAccountTotal implements 
    Database.Batchable<sObject>, Database.Stateful{

   global final String Query;
   global integer Summary;
  
   global SummarizeAccountTotal(String q){Query=q;
     Summary = 0;
   }

   global Database.QueryLocator start(Database.BatchableContext BC){
      return Database.getQueryLocator(query);
   }
   
   global void execute(
                Database.BatchableContext BC, 
                List<sObject> scope){
      for(sObject s : scope){
         Summary = Integer.valueOf(s.get('total__c'))+Summary;
      }
   }

global void finish(Database.BatchableContext BC){
   }
}

Monday, 19 February 2018

Pass parameters From lighning component controller to controller

By using component.get(v.attrinuteName) or  component.find("aura:id").get("v.value") we can pass value from component to controller.
By using component.set("v.attrinuteName",value);  we can pass value from controller to lightning component.

In below code empName attribute used to store the data which is entered by user in ui:inputText.
when user click on button "callme" function gets called and the value entered in the input text box will be passed to the attribute "empName" and the result will be printed.
<aura:component >
    <aura:attribute name="empName" type="String"/>
    <aura:attribute name="emp" type="String"/>
    <ui:inputText label="Enter Name"  aura:id="name" />
    <ui:button label="submit" press="{!c.doInit}" /> <br />
    Employee Name Entered:  <ui:outputText value="{!v.empName}" />
</aura:component>


Firstcomponent.js

({
    doIniti: function(component, event, helper) {
    var Name = component.find("name").get("v.value");
    component.set("v.empName",Name )
    }
})
Check Output
FitstComponentApp.app

<aura:application >
    <c:FirstComponent />
</aura:application>

Sunday, 18 February 2018

Debugging in lightning client side controller

Client side log message for lightning component.
Why to use?

1. Suppose we want to check any log message in our client side controller or helper method.
2. Suppose we want to check a client side controller or helper method is calling from a button click or not.
3. Suppose we want to check user request parameter(s) is coming properly or not to a client side controller or helper method.
4. Suppose we want to check server-side response.


How to develop?

In your controller or helper method use the below line of code,

console.log("Your condole log message.");


How to check?

Suppose we have a "Save" button in our lightning component and click on "Save" button will call a controller "doSave()" method.
Now we want to check is this method is calling or not? So, create a console.log("I am under doSave method.") under this doSave() method. Now open this component in browser and also open console window [For eg. to open console window in google chrome use "Ctrl + Shift + i "].
Now click on "Save" button and check console window and if every thing is OK, then we will see log message as "I am under doSave method." in console window.

Friday, 9 February 2018

Roll up Trigger

trigger RollUptrg on Contact(after insert, after update, after delete, after undelete){
Set<id> accIds = new Set<Id>();
    if(trigger.isInsert || trigger.isUpdate || trigger.isUndelete){
for(Contact con: trigger.new){
if(con.AccountId != null){
accids.add(con.AccountId);
}
}
}
    if(trigger.isUpdate || trigger.isDelete){
        for(contact con: trigger.old){
if(con1.AccountId != null){
accids.add(con.AccountId);
}
}
    }
if(accids.size()>0){
List<Account> lst = [Select id, number_of_contacts__c,(Select id from Contacts) from Account where id in: accids];
for(Account acc : lst){
acc.number_of_contacts__c = acc.contacts.size();
}
update lst;
}
}

SOQL Injection



What is SOQL Injection in salesforce?
Suppose you have a search form and instead of typing a valid search parameter, User types something invalid text and that can make your SOQL query invalid and expose the unexpected result.

It's a SQL example, but describe the SOQL injection as well in a good manner.
So here you can see that. In the User id field once user puts an invalid parameter and goes to the controller and form a query that results in an invalid login.

The worst scenario could be if resultant data from a query supposed to be deleted.
 let's have one more quick example for this :

I have a case where I want to delete the Account based on name entered in the input name field on the page.
Implementation can be like this :

List<Account> listAccount = Database.query('Select id from Account where Name = \'' + nameField + '\' '); 

delete listAccount;


It works great with a valid value.
 Now it can be worst if value of nameField is provided like :

nameField = \' OR Id != null OR Type != \'


So once the action will be performed, this will be bind-up with the query and resultant query will be like this :
  

List<Account> listAccount = Database.query('Select id from Account where Name = \'\'\' OR ID != null OR Type != \'\' ');

delete  listAccount;


So hopefully, you can see the monster here. It will delete the entire database for account records.

Salesforce provides escape functions to get rid of SOQL injection. 
The solution can be one of the followings:
  1. Try to use STATIC queries as much as possible. The STATIC query has inbuilt escaping.
  2. If dynamic query is needed , then all the search parameters should use escapeSingleQuotes() function.like
    List<Account> listAccount = Database.query('Select id from Account where Name = \'' + String.escapeSingleQuotes(nameField) + '\' ');
String.escapeSingleQuotes method adds the escape character (\) to all single quotation marks in a string that is passed in from a user. The method ensures that all single quotation marks are treated as enclosing strings, instead of database commands.