Apex Trigger Examples || Salesforce Apex Triggers

Basic Apex Trigger Examples:



1.DemoTtrigger1

DemoTtrigger1 Populates Description field with the user first name who creates or updates the record by using userInfo standard keyword . And also does not allow user to delete the record .

trigger DemoTtrigger1 on Author__c (before insert,before update,before delete) {
    If(trigger.isInsert){
        for(Author__c Author: Trigger.new){
            //Populates Description with the user first name who creates the record
            Author.Description__c = 'Author Created by '+ userInfo.getFirstName(); 
        }
    } else
        If(trigger.isUpdate){
            for(Author__c Author: Trigger.new){
          //Updates Description with the user first name who updates the record
                Author.Description__c = 'Author Last updated by '+ userInfo.getFirstName();   
            }
        }
    if(Trigger.isDelete&&Trigger.isbefore){ 
        for(Author__c Rec:trigger.old) 
        {
          //User gets the below error when user tried to delete the record
            Rec.adderror('You Cannot Delete the Author Record');
        }
    }
}


2.DemoTrigger2

Whenever new account record creates"Account_Rep__c"  updates with the account owner name.
  
trigger DemoTrigger2 on Account (before insert) {
    Set<Id>setAccOwner=new Set<Id>(); 
    for(Account Acc: trigger.new) 
    { 
        setAccOwner.add(Acc.OwnerId);     
    }
    map<id,user>userMap=new map<id,user>();
    for(user u:[select id,Name from user where id IN:setAccOwner]){
        userMap.put(u.id,u);
    }
    for(Account Acc: Trigger.new)
       
    { 
        User usr=UserMap.get(Acc.OwnerId); 
        system.debug('usr');
        Acc.Account_Rep__c=usr.Name; 
    }
}

Note :Most of the examples here made use of  Map/List .If you are not sure about the Map/List concepts ,Please make use of below post which clearly explains about collections in salesforce .
https://salessforcehacks.blogspot.com/2020/01/collections-in-salesforce-list-set-map.html

  3.DemoTrigger3

DemoTrigger3 prevents user to delete contact which is associated with the any account. When user tries to delete associated contact ,User will be presented with the error "Contact associated with account cannot be deleted"




trigger DemoTrigger3 on Contact (before delete) {
    //Contact with associated account cannot be deleted
   if(Trigger.isDelete&&Trigger.isbefore){
    for(contact con:Trigger.old){
        if(con.accountId!=null){
            con.addError('Contact associated with account cannot be deleted');
        } 
       
    }}

4.DemoTrigger4

 Creates opportunity record if the account doesn't contain at least one opportunity.

trigger DemoTrigger4 on Account(after insert, after update) {
    List<Opportunity> oppList = new List<Opportunity>();
   
    // Get the related opportunities for the accounts in this trigger
    Map<Id,Account> acctsWithOpps = new Map<Id,Account>(
        [SELECT Id,Name,(SELECT Id,Name FROM Opportunities) FROM Account WHERE Id IN :Trigger.New]);
    System.debug('acctsWithOpps  ::'+acctsWithOpps);
   
    // Add an opportunity for each account if it doesn't already have one.
    // Iterate through each account.
    for(Account a : Trigger.New) {
        System.debug('acctsWithOpps.get(a.Id).Opportunities.size()=' + acctsWithOpps.get(a.Id).Opportunities.size());
        // Check if the account already has a related opportunity.
        if (acctsWithOpps.get(a.Id).Opportunities.size() == 0) {
            // If it doesn't, add a default opportunity
            oppList.add(new Opportunity(Name=a.Name + ' Opportunity',
                                       StageName='Prospecting',
                                       CloseDate=System.today().addMonths(1),
                                       AccountId=a.Id));
        }         
    }
    if (oppList.size() > 0) {
        insert oppList;
    }
}

5.DemoTrigger5

 DemoTrigger5 send email notification after new student record created into the system.               Trigger makes use of handler class to send an email notification. Trigger collects newly created     student records and send them to the handler class to process further for the email   notification.

trigger DemoTrigger5 on student__c (After insert) {
   if(Trigger.isinsert&&Trigger.isafter){
       StudentEmailNotification.sendMail(Trigger.new); 
   }

}

class :

public class StudentEmailNotification {
    // Public method
    public static void sendMail(List<student__c> stuList) {
        // Create an email message object
        system.debug('stuList in sendmail method :'+stuList);
        for(student__c st :stuList){
            Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
            String address=st.Email__c;
            String[] toAddresses = new String[] {address};
            String ccAddresses=st.Class_Owner_Email__c ;
            system.debug('ccAddresses :'+ccAddresses);
            String[] setCcAddresses=new String[] {ccAddresses};
            mail.setToAddresses(toAddresses);
            mail.setCcAddresses(setCcAddresses);
            mail.setSubject('Student Registration Notification');
            mail.setPlainTextBody
                ('The Student' + st.Name + ' Registration is Completed with the below details :'+'\n\n' +
                 'Student Name : ' + st.Name + '\n\n'+
                 'Request Email : ' +st.Email__c + '\n\n' +
                 'Class: ' +st.Class__c+ '\n\n' +
                 'Please reach out to System Administrator if you require any further information');
            Messaging.SendEmailResult[] results = Messaging.sendEmail(
                new Messaging.SingleEmailMessage[] { mail });
        }
    }
}

6.DemoTrigger6 

 Updates "Associated_Contacts__c" with the number of contacts associated with the account .   Whenever new contact creates/removed from the account ,The respective count would be   increased/Decreased accordingly. 

trigger DemoTrigger6 on Contact (before delete,before insert,after insert,after delete,after update) {
    //Update count of the contact to the 'Associated Contacts' field in the account
    set<id> accid=new set<id>();
    list<contact> contactlist =new list<contact>();
    list<contact> listcon=new list<contact>();
    list<account> listAcc=new list<account>();
    list<account> acclist=new list<account>();
    map<id,integer> mapCount=new map<id,integer>();
    
    if(trigger.isinsert){
        
        for(contact con:trigger.new){
            
            accid.add(con.accountid);
            
        }
        
    }
    
    if(trigger.isdelete){
        
        for(contact con:trigger.old){
            
            accid.add(con.accountid);
            
        }
        
    }
    
    acclist=[select id,name,Overall_Contacts_Status__c from account where id in:accid];
    
    contactlist = [select id,Status__c,name,accountid from contact where accountid in:accid];
    
    for(account acc:acclist){
        
        listcon.clear();
        
        for(contact c:contactlist){
            
            if(c.accountid==acc.id){
                
                listcon.add(c);
            }
        }
        mapCount.put(acc.id,listcon.size());
    }
    if(acclist.size()>0){
        for(Account a:acclist){
            if(mapCount.get(a.id)==null)
                a.Associated_Contacts__c=0;
            else
                a.Associated_Contacts__c=mapCount.get(a.id);
            listAcc.add(a);
        }
    }
    if(listAcc.size()>0)
        update listAcc;    

}  
 //you can also reduce the code with account inner query like below

trigger DemoTrigger6 on Contact (before delete,before insert,after insert,after delete,after update) {
 set<id> accountIds=new set<id>();
    List<account> accList=new List<account>();
    map<id,integer> noOfContacts=new map<id,integer>();
    List<account> updateaccList=new List<account>();
    if(Trigger.isinsert||Trigger.isUpdate&&Trigger.isafter){
        for(contact con:Trigger.new){
            if(Trigger.isinsert){
                accountIds.add(con.accountId);
            }else if(Trigger.isUpdate&&trigger.oldmap.get(con.id).accountId!=null&&con.accountId==null){
                accountIds.add(trigger.oldmap.get(con.id).accountId);
            }
        }
    }
    if(Trigger.isDelete&&Trigger.isafter){
        for(contact con:Trigger.old){
            accountIds.add(con.accountId);
        }
        
    }
    system.debug('accountIDs:'+accountIds);
    accList=[select id,(select id,accountId from contacts) from account where id IN:accountIds];
    
    for(account acc:accList){
        if(acc.contacts.size()>0){
            acc.Associated_Contacts__c=acc.contacts.size();
        }else{
            acc.Associated_Contacts__c=0; 
        }
        updateaccList.add(acc);
    }
    system.debug('updateaccList:'+updateaccList);
    update updateaccList;
}


7.DemoTrigger7

DemoTrigger7 helps to avoid recursive trigger by using the handler.

trigger DemoTrigger7 on Account (after insert) {
     if(RecursionExampleHandler.isFirstTime){
          RecursionExampleHandler.isFirstTime=false;
    for(account a:Trigger.new){
        account acc=new account();
     acc.Name='Recursive Test';
        insert acc;
    }
     }
}

class :

public class RecursionExampleHandler {
public static Boolean isFirstTime=True;
}

You can also visit below post to know more about recursive trigger scenario
https://salessforcehacks.blogspot.com/2019/12/salesforce-recursive-triggers-fully.html 

8.Apex Managed Sharing :

Until now Most of us know the methods of sharing the records across organization by using sharing rules  and OWD ,This example helps us to share records in programmatic way(Apex Trigger/Apex Class) for the complex business requirements .


Scenario Based Example:

Prerequisite:

Objects Used in the discussion:

1.Project--Object contains all the business task details which require to be completed .

2.Project Member--Are the members who work on the project which has assigned to them.
   Project Member is junction object which is master-Detail with Project and Contact


3.Contact--Sales force Contact Object
   Assume all the contacts Owner is assigned with their own User ID .
Eg .We have user Kris who is also Owner for associated contact named Kris .

Use Case :

1.Whenever status of the project changed from 'New' to 'Assigned' The respective project record access should be shared with all the Project Members .

2.Once the Project Members completed their assigned task and Status of the Project changes to 'Completed' then Access should be Revoked/Removed from the Project Team Members .

Solution: 

We require to create Apex Trigger on Project object and create the share object records and delete the access after Project completed

The below Trigger collects all the project records for which status changed to 'Assigned' Or changed to 'Completed' and send them to Apex class to create and Revoke the access respectively  by using apex sharing .

Apex Trigger :

trigger ProjectShare on Project__c (after update) {

    List<Project__c > projectShareList=new List<Project__c >();

    List<Project__c > revokeShareList=new List<Project__c >();

    //Share the access

    if(Trigger.isafter&&Trigger.isUpdate){
   
        for(Project__c Pro:Trigger.new){
       
            if(Pro.Status__c=='Assigned'&&trigger.oldmap.get(Pro.id).Status__c!='Assigned'){
           
                projectShareList.add(Pro);
           
                system.debug('Share the access'+Pro.id);
           
            }
       
        }
     
        if(projectShareList!=null){
         
            ProjectShareclass.provideAccess(projectShareList);
           
        }
   


        //Revoke the access
   
        for(Project__c Pro:Trigger.new){
       
            if(Pro.Status__c!='Assigned'&&trigger.oldmap.get(Pro.id).Status__c=='Assigned'){
           
                system.debug('Revoke the access'+Pro.id);
           
                revokeShareList.add(std);
           
            }
       
        }
        if(revokeShareList!=null){
       
            ProjectShareclass.revokeAccess(revokeshareList);
       
        }
    }
}

Apex Class :

    public static void  provideAccess(List<Project__c > pros){
   
        List<Project_member__c> tmList=new List<Project_member__c>();
   
        map<id,Project_member__c> tmmap=new map<id,Project_member__c>();
   
        List<Project__Share> shareList=new List<Project__Share>();
   
       tmList=[select id,project__c,MasterDetailWithcontact__r.owner.id from Project_member__c where Project__c IN:pros];
        for(Project_member__c s:tmList){
       
            tmmap.put(s.Project__c,s);
       
        }
   
        for(Project__c rec:Pros){
       
            Project__Share share=new Project__Share();
       
            share.ParentId = rec.id;
       
            share.AccessLevel = 'Edit';
       
            share.RowCause = Schema.Project__Share.RowCause.Manual;
       
            share.UserOrGroupId = tmmap.get(rec.id).MasterDetailWithcontact__r.owner.id;
       
            shareList.add(share);
       
        }
   
        insert shareList;
   
    }

    public static void  revokeAccess(List<Project__c> pros){
   
        List<Project__Share> shareList=new List<Project__Share>();
   
        shareList=[select id from Project__Share where parentId IN:pros AND RowCause = 'Manual'];
   
        delete shareList;
    }
}

Result :

Once the project record is created into the database ,By default only owner of the record will have access to record as shown in Screenshot 2 :

Screenshot 2:



Once the above project record updated to the 'Assigned' status  ,Access of the project record will be shared to project team member . Please find the ScreenShot 3.

First Share record with all access Level belongs to the default record owner access . And Second Share record with Edit access and RowCause 'Manual' belongs to Share record created by above Apex trigger and Apex class.

ScreenShot 3 :





If you update the Status to 'Completed' again the 'Edit' access would be revoked/Deleted to all the Project Members associated to Project object.
*********************************************************************

What is apex trigger in salesforce,Triggers in salesforce,Apex triggers,Basic apex trigger examples in salesforce,Apex trigger real time scenarios ,apex trigger with hands on examples.

*********************************************************************
We hope you are clear with the process now .

If you still require further clarifications,Please let us know in the comments .

Please follow us for more salesforce concepts.
Happy Learning☺☺☺


8 comments:

  1. This is applicable to lightning yes?

    ReplyDelete
  2. Thank you mate .examples are very clear

    ReplyDelete
  3. If I'm not wrong we can only use (before delete) event in 3rd example.

    ReplyDelete
  4. I learned many basics still not able to write code.Please help me out on this.give me some technics

    ReplyDelete
  5. If u start writing a code try to put more system.debug on each line so that u can understand line by line what was the executing while running a trigger

    ReplyDelete
  6. Thanks for the valuable Content. I really learned a lot here. Do share more like this.
    Sales Force Testing
    Salesforce Automation Testing

    ReplyDelete
  7. Very useful information

    ReplyDelete