Thursday 25 February 2016

Trigger Basic Level Programs

Before Insert :
==================
Q::Which Trigger Context variables are allowed in  before insert.
Ans :
-------------------------------------------------------------------------------
Trigger.New Trigger.NewMap Trigger.old Trigger.oldMap
--------------------------------------------------------------------------------
before insert   Yes No No No


Q:: Which Operations are allowed on Trigger.New in before insert trigger

Ans:
Trigger.New
----------------------------
Read Write SOQL DML
----------------------------
Yes Yes No No

Scenario

 ==>>Basic Level Trigger scenario's on before insert

Scenario 1: When ever we are trying to insert new Account record with industry
   as banking  then  Annualrevenue should be set as 50000;

Code :
trigger scenario1 on Account (before insert) {
    for(Account a:Trigger.New){
        if(a.industry=='Banking'){
            a.annualRevenue=50000;
        }      
    }
}

Test Class :

@isTest
private class Scenario1Test {
@isTest
    static void test(){
        Integer count=[select count() from Account];
        Account a1=new Account(Name='aaa',Industry='Banking');
        try{
        insert a1;
        }catch(Exception e){
            System.debug(e);
        }
        Integer size=[select count() from Account];
        System.assertEquals(count+1,size);
        Account acc=[select id, AnnualRevenue from Account where id=:a1.id];
        System.assertEquals(acc.annualRevenue,50000);
       
    }
}

Scneario 2: When ever new Account is creatd with out phone no it should throw
  error message

Trigger :
trigger scenario2 on Account (before insert) {
    for(Account a:Trigger.New){
        if(a.phone=='' || a.phone==null){
            a.addError('Phone no is a must ');
        }
    }
}

Test Class :
@isTest
private class scenario2 {
@isTest
    static void testme(){
        Integer count=[select count() from Account];
        Account a=new Account(Name='aaa');
        try{
            insert a;
        }catch(Exception e){
            System.debug(e);
        }
        Integer size=[select count() from Account];
        System.assertEquals(count,size);
    }
}


Scneario 3:When ever new Application is created with Application Type as New

1. If pancard no is already existing in the black list then
  set application status as rejected

2.If the pancard no is not available in black list set the application
 status as pending

Solution:
Object :Application
Fields : Type : PicKList (New ,cancel,Block)
Status : PickList( Approved,Rejected,Pending)
Pancard: Text

Object: BlackList
Fields  : Name : Text

Trigger Code:

trigger scenario3 on Application__c (before insert) {
   List<String> pancards=new List<String>();
   for(Application__c ap:Trigger.New){
   if(ap.Type__c=='New')
       pancards.add(ap.Pancard__c);
   }
   List<BlackList__c> black=[select id,Name from BlackList__c where name in :pancards];
   Set<String> panList=new Set<string>();
   if(black.size()!=0){
       for(BlackList__c b:black){
            panList.add(b.name);
        }
   }
   for(Application__c a:Trigger.New){
       if(panlist.contains(a.pancard__c)){
           a.status__c='Rejected';
       }else{
            a.status__c='Pending';
       }
   }
}


Test Class :
@isTest
private class Scenario3 {
    testmethod static void testme(){
       
        BlackList__c b1=new BlackList__c();
        b1.Name='1234';
        insert b1;
        Application__c ap1=new Application__c();
        ap1.Applicant_Name__c='aaa';
        ap1.Type__c='New';
        ap1.Pancard__c='1234';
        insert ap1;
        Application__c res1=[select id,status__c from Application__c where id=:ap1.id];
        System.assertEquals(res1.Status__c,'Rejected');
       
        Application__c ap2=new Application__c();
        ap2.Applicant_Name__c='aaa';
        ap2.Type__c='Block';
        ap2.Pancard__c='4567';
        insert ap2;
        Application__c res2=[select id,status__c from Application__c where id=:ap2.id];
        System.assertEquals(res2.Status__c,'Pending');
        Application__c ap3=new Application__c();
        ap3.Applicant_Name__c='aaa';
        ap3.Type__c='New';
        ap3.Pancard__c='3456';
        insert ap3;
        Application__c res3=[select id,status__c from Application__c where id=:ap3.id];
        System.assertEquals(res3.Status__c,'Pending');
       
    }

}

Scenario 4: When ever new Account is  created successfully corresponding contact
should be created using the details from Account

Trigger :

trigger scenario4 on Account (after insert) {
List<Contact> cons=new List<Contact>();
    for(Account a:Trigger.New){
        Contact c=new Contact();
        c.lastname=a.name;
        c.phone=a.phone;
        c.accountid=a.id;
        cons.add(c);
    }
    insert cons;
}

TestClass :
@isTest
private class scenario4Test {
@isTest(seealldata=true)
    static void testme(){
        Integer accCount=[select count() from Account];
        Integer conCount=[select count() from Contact];
        Account a=new Account(Name='aaa',Phone='123');
        try{
            insert a;
        }catch(Exception e){
            System.debug(e);
        }
        Integer count=[select count() from Account];
        Integer size=[select count() from Contact];
        System.assertEquals(acccount+1,count);
        System.assertEquals(conCount+1,size);
        Contact con=[select accountid from Contact where accountid=:a.id];
        System.assertEquals(con.lastname,a.name);
        System.assertEquals(con.phone,a.phone);
        System.assertEquals(con.accountid,a.id);
    }
}


Scenario 5: When ever a new Opportunity is created .Then share that record with
 user

Note : before you write the trigger
OWD: opporutnity  :Private

Trigger:
trigger scenario5 on Opportunity (after insert) {
User u=[select id from User where alias='kshar'];
    List<OpportunityShare> records=new List<opportunityShare>();
    for(Opportunity op:Trigger.New){
        OpportunityShare share=new OpportunityShare();
        share.OpportunityId=op.id;
        share.rowCause='Manual';
        share.OpportunityAccessLevel='Edit';
        share.UserOrGroupId=u.id;
        records.add(share);
    }
    insert records;
}


____________________
__________________



trigger example on Application__c (before insert,after insert) {
    if(Trigger.isInsert && Trigger.isBefore){
        for(Application__c a:Trigger.New){
            if(a.ID_Proof__c!='Pancard'){
                a.Address_Proof__c=a.ID_Proof__c;
            }
           
        }
    }
    if(Trigger.isAfter && Trigger.isInsert){
        List<Application__c> newList=[select CreditLimit__c,Salary__C from Application__c where id in:Trigger.New];
        for(Application__c ap:newList){
            if(ap.salary__c>50000){
                ap.CreditLImit__c=3*ap.salary__C;
            }else{
                ap.CreditLImit__c=2*ap.salary__c;
            }
        }
        update newList;
    }

}




===========================================
Scenario 1: When ever a new Account record is  inserted if the industry is
   'Banking' set the annualrevenue as 50,00,000  before insert

Code :

trigger annualexample on Account (before insert) {
    List<Account> accs=Trigger.New;
    for(Account a:accs){
        if(a.industry=='Banking')
            a.annualRevenue=5000000;
    }

}

Test Class :
@isTest
public class AnnualTest {
@isTest
    static void testme(){
        Integer count=[select count() from Account];
        Account a1=new Account(Name='aaa',Industry='Banking');
        Account a2=new Account(name='bbb',Industry='Energy');
        try{
            insert a1;
            insert a2;
        }catch(Exception e){
            System.debug(e);
        }
        Integer size=[select count() from Account];
        System.assertEquals(size,count+2);
        Account acc=[select annualrevenue from Account where id=:a1.id];
        System.assertEquals(acc.annualRevenue,5000000);
        Account acc1=[select annualrevenue from Account where id=:a2.id];
        System.assertNotEquals(acc1.annualRevenue,a1.AnnualRevenue);
    }
}

=====================================================================

Scenario 2:
Object   : Account
 
Validation Rule : if the annualrevenue < 10,000 then throw error

Trigger  :Create a before insert tigger on Account w which will modify the
          annualrevenu of new records which we are inserting as 5,00,000


Code: trigger annualvalidation on Account (before insert) {
    for(Account a:Trigger.New){
        a.annualRevenue=500000;
    }
       }

Test Class :
@isTest
private class AnnualValidation {
   @isTest
    static void testme(){
        Integer count=[select count() from Account];
        Account a=new Account(Name='bbb',AnnualRevenue=900);
        try{
            insert a;
        }catch(Exception e){
            System.debug(e);
        }
        Integer size=[select count() from Account];
        Account acc=[select annualRevenue from Account where id=:a.id];
        System.assertEquals(size,count+1);
        System.assertEquals(acc.annualRevenue,500000);
       
    }

}
======================================================================
Scenario 3:

Object : Account
Trigger: After Insert

Description : When ever new Account record is successfully created  then
     create the corresponding  contact record for the account
with
account name as contact lastname
account phone as contact phone

Trigger Code:

trigger accountAfter on Account (after insert) {
    List<Contact> cons=new List<Contact>();
    for(Account a: Trigger.New){
        Contact c=new Contact();
        c.accountid=a.id;
        c.lastname=a.name;
        c.phone=a.phone;
        cons.add(c);
    }
    insert cons;

}

Test Class  :

@isTest
private class AccountAfter {
@isTest
    static void testme(){
        Integer count=[select count() from Account];
        Integer size=[select count() from Contact];
        Account a=new Account(Name='Testing',phone='111');
        try{
            insert a;
        }catch(Exception e){
            System.debug(e);
        }
        Integer newCount=[select count() from Account];
        Integer newsize=[select count() from Contact];
        Contact c=[select lastname,phone from Contact where accountid=:a.id];
        System.assertEquals(c.lastname,a.name);
        System.assertEquals(c.phone,a.phone);
    }
}

Create a New Account Record  and test it

====================================================================
Scenario :4

Object : Account

Trigger :  before Update

  When ever  the  phone no  in the account record  is modified
  then  fetch all the contacts of the account record and update the
 contact otherphone  no field  value with account  phone  no field value;

Trigger Code:

trigger accountphone on Account (before update) {
    List<ID> accs=new List<ID>();
    Map<Id,Account> oldMap=Trigger.oldMap;
    Map<Id,Account> newMap=Trigger.NewMap;
    for(Id aid:oldMap.keySet()){
        if(oldMap.get(aid).phone!=newMap.get(aid).phone)
            accs.add(aid);
    }
    List<Contact> conList=[select otherphone,accountid from contact where accountid in:accs];
    if(conList.size()>0){
    for(contact c:conList){
        c.otherphone=newMap.get(c.accountid).phone;
    }
    update conList;
    }
}

Test Class :

@isTest
public class accountphone {
@isTest
    static void testme(){
        Account a=new Account(Name='aaa',Phone='111');
        insert a;
        Contact c=new Contact(lastname='aaa',otherphone='222',accountid=a.id);
        insert c;
        String newPhone='333';
        Account rec=[select phone from Account where id=:a.id];
        rec.phone=newPhone;
        update rec;
        Account acc=[select phone from Account where id=:a.id];
        System.assertEquals(acc.phone,newPhone);
        Contact c1=[select otherphone from Contact where accountid=:a.id];
        System.assertEquals(c1.otherphone,rec.phone);
       
       
    }
}

===================================================
Scenario : 5
Object : Account

Trigger :after update

Logic : When ever account record  Active field value is updated  as No

then delete  the corresponding contacts

Trigger Code:
trigger accountActive on Account (after update) {
List<Id> idList=new List<Id>();
    Map<Id,Account> oldMap=Trigger.OldMap;
    Map<Id,Account> newMap=Trigger.NewMap;
    for(Id aid:oldmap.keySet()){
        if(oldMap.get(aid).Active__c=='Yes' && newMap.get(aid).Active__c=='No'){
            idList.add(aid);
        }
    }
    List<contact> conList=[select id from Contact where accountid in:idList];
    delete conList;
}

Test Class :

@isTest
private class AccountActive {
@isTest
    static void testme(){
        Account a1=new Account(Name='aaa',Active__c='Yes');
        insert a1;
        Contact c1=new Contact(lastname='test',accountid=a1.id);
        insert c1;
        Account acc=[select id,Active__c from Account where id=:a1.id];
        acc.Active__c='No';
        update acc;
        Integer count=[select count() from Contact where accountid=:acc.id];
        System.assertEquals(count,0);
        /* Changing the value from No to Yes */
        Contact c2=new Contact(lastname='test',accountid=a1.id);
        insert c2;
        Account acc1=[select id,Active__c from Account where id=:a1.id];
        acc1.Active__c='Yes';
        update acc1;
        Integer count1=[select count() from Contact where accountid=:acc1.id];
        System.assertNotEquals(count1,0);
    }
}
====================================================================
Scenario : 6
Object   : Account

Logic : when ever we try to delete a account record which has contacts it
should throw the error

Trigger Code:

trigger accountDelete on Account (before Delete) {
List<Account> accs=[select id,(select id from contacts ) from Account where id in:Trigger.old];
    for(Account a:accs){
        if(a.contacts.size()>0)
            a.addError('Account cannot be deleted where it has contacts');
    }
}

======================================================================
Scenario: 7

Object : Account

Logic :
1. When we  try to insert a new Account Record
2. Before the record is inserted
3. It should check wheather there are any any account records already
           exits in Account object  with the same name  of new Account
  we are inserting
4. if it exits throw error message


Trigger Code: This code is not a good practice as they we have written
soql with in a for loop

trigger dulicateCheck on Account (before insert) {
   /* if there are more than 100 records which are inserting this will throw
    * Too many soql :101 error  on the below code
   */
    for(Account a:Trigger.New){
        Integer count=[select count() from Account where name=:a.name];
        if(count>0){
            a.addError('Duplicate Name Exists');
        }
    }
 

}

Trigger code with Good practices

/* Already in the Account Object we have  the following records
 * =============================
 * |Name | Industry |
 * -------------------------------
 *  Wipro Banking
 *  Accenture Technology
 *  TCS Banking
 *  DELL Banking
 * ==============================
 * In that Account object we are trying to insert new Records
 * ========================
 * Name Industry          These two records are in Trigger.New
 * =======================
 *  Wipro Technology
 *  Accenture Banking
 *  Capital Education
*/
trigger dulicateCheck on Account (before insert) {
 
  List<String> names=new List<String>();
    for(Account a:Trigger.New){
        names.add(a.name);
    }
    /* names will contain {wipro, Accenture,Capital} */
    /* SOql query will all the account records whoes names are {Accenture,Wipro,Capital} */
    List<Account> dupAccount=[select id,name from Account where name in:names];
    /*Above query will fetch the records
     * Wipro Banking
  * Accenture Technology
  * and keep then in dupName
  */
    Set<String> dupNames=new Set<String>();
    for(Account a:dupAccount){
        dupNames.add(a.name);
    }
    /* dupNames will contain {wipro,Accenture} */
    for(Account a1:Trigger.New){
        /* if name of the new record is in dupNames then throw error */
        if(dupNames.contains(a1.name)){
            a1.addError('Duplicate Record already Exists');
        }
    }
   
}


Test Code:
@isTest
private class DupNamesTest {
    @isTest
    static void testme(){
        String accname='Testing';
        Account a1=new Account(Name='accName');
        insert a1;
        Integer count=[select count() from Account where Name=:accName];
        Account a=new Account();
        a.name=accName;
        try{
            insert a;
        }catch(Exception e){
            System.debug(e);
        }
          Integer size=[select count() from Account where Name=:accName];
        if(count>0){
            System.assertEquals(count,size);
        }else{
            System.assertEquals(size,count+1);
        }
           
    }

}

================================================
Scenario : 8

Object : Opporutnity

Logic :
1.When ever new opporutunity is created  with amount > 50000
or
existing opporutnitis update with amount > 50000

2.then  Apex sharing rule and share the record with
 User: karthic

Apex Sharing :

1. Every object internally has corresponding sharing object


Ex: opporutity-------OpporutnityShare

   Account ---------AccountShare

   Customer__c------Customer__Share

   Transaction__c---Transaction__Share


2. If we want to create Apex sharing rules OWD on the object
  should be private |Public Read

3. We can grant access of Read| Write

4. ApexSharing rule with  OpporutnityShare we have to provide
  the following data

1.OpportunityId : This is the id of the opporutnity record
          which we to share

2.OpportunityAccessLevel : Type of the access we want to grant
on the record

values : Read |Edit| All

3.RowCause  :This will specify reason for sharing

values : Manual |Rule |Sales Team |Owner

4. UserOrGroupId : This is the id of the user or group with
whom we want to share



Trigger code :

trigger shareRecord on Opportunity (after insert,after update) {
    List<OpportunityShare> share=new List<OpportunityShare>();
    User u=[select id from User where alias='kshar'];
    for(Opportunity op:Trigger.New){
        if(op.amount>50000){
            OpportunityShare p=new OpportunityShare();
            p.OpportunityId=op.id;
            p.UserOrGroupId=u.id;
            p.OpportunityAccessLevel='Read';
            p.RowCause='Manual';
            share.add(p);
        }
    }
    insert share;

}

===================================================
Scenario : 9

Object   : Application__c

Logic    : When ever new application
 Before Insert
 1. Check the pancard no of the application record is in the
    black list  object
 2.If pancard is in the black lsit set the status as rejected
otherwise set status as pending
   

 2. If the record status is updated as Approved then create
    new customer record with same details of the application
Step 1: Create Application Object with follwing fields

   Field : LastName : Text
 : FirstName: Text
 : PanCard  : Text
 : Status   : PickList(Pending,Rejeced,Approved)

Step 2: Create Customer Object with following fields

 Field : LastName : Text
 : FirstName: Text
 : PanCard  : Text


Step 3: Create BlakcList Object with the following fields

Field : Pancard :Text



Trigger handler class :


public class ApplicationHandler {
    public Static void afterUpdate(Map<Id,Applicaiton__c> old ,List<Application__c> appList){
        List<Customer__c> custList=new List<Customer__c>();
        for(Application__c a:appList){
            if(old.get(a.id).Status__c!='Approved' && a.status__c=='Approved' ){
                Customer__c c=new Customer__c();
                c.lastName__c=a.lastName__c;
                c.FirstName__c=a.FirstName__c;
                c.pancard__c=a.pancard__c;
                custList.add(c);
            }
        }
        insert custList;
    }
    public static void  beforeInsert(List<Application__c> appList){
        List<String> pancards=new List<String>();
        for(Application__c a:appList){
            pancards.add(a.pancard__C);
        }
        List<BlackList__c> blist=[select pancard__C from BlackList__c where Pancard__c in: pancards];
Set<String> duplicates=new Set<String>();
        for(BlacklIst__c b:blist){
            duplicates.add(b.pancard__C);
        }
        for(Application__c ap:appList){
            if(duplicates.contains(ap.pancard__c)){
                ap.status__C='Rejected';
            }else{
                ap.Status__c='Pending';
            }
        }
    }

}

Trigger :

trigger appTrigger on Application__c (before insert,after update) {
    if(Trigger.isBefore && Trigger.isInsert){
        ApplicationHandler.beforeInsert(Trigger.new);
    }
    if(Trigger.after && Trigger.update){
        ApplicationHandler.afterUpdate(Trigger.oldMap,Trigger.new);
    }

}

=================================================================

Scenario :10

Recursive Trigger:

If a trigger calls itself we call it as recursive Triggers.

Ex: if we have written a  insert trigger on a object  and with in
   the trigger if we are trying perfom insert operation on the
   same object  then it will throw recursive trigger



Example :

trigger contactRecords on Contact (before insert) {
    Contact c1=new Contact(lastname='Testing');
    insert c1;

}

Above trigger will throw recursive trigger exception .

Recursive triggers are handled using static boolean flag varibles

Quick Example :


public class Contacthandler {
    public Static boolean flag =true;
    public static void beforeInsert(){
        if(flag==true){
            flag=false;
            Contact c1=new Contact(lastname='Recursive');
            insert c1;
        }
    }

}

Trigger:

trigger contactRecords on Contact (before insert) {
    Contacthandler.beforeInsert();
}

=======================================
1.























































UPDATE





======================================================================
befor Update Triggers
=======================================================================

1.On  the records which are Trigger.New in before Update

Trigger.New
------------------------------
 Read Write SOQL DML
-------------------------------
 Yes Yes No No

2.On  the records which are Trigger.NewMap in before Update

Trigger.NewMap
------------------------------
 Read Write SOQL DML
-------------------------------
 Yes Yes No No

3.On  the records which are Trigger.old in before Update

Trigger.old
------------------------------
 Read Write SOQL DML
-------------------------------
 Yes No Yes No


4. On  the records which are Trigger.oldMap in before Update

Trigger.oldMap
------------------------------
 Read Write SOQL DML
-------------------------------
 Yes No Yes No

===============================================================
after Update Trigger
================================================================

1.On  the records which are Trigger.New in after Update

Trigger.New
------------------------------
 Read Write SOQL DML
-------------------------------
 Yes No Yes Yes


2. On  the records which are Trigger.NewMap in after Update

Trigger.NewMap
------------------------------
 Read Write SOQL DML
-------------------------------
 Yes No Yes Yes

3.On  the records which are Trigger.old in after Update

Trigger.old
------------------------------
 Read Write SOQL DML
-------------------------------
 Yes No No No


4. On  the records which are Trigger.oldMap in after Update

Trigger.oldMap
------------------------------
 Read Write SOQL DML
-------------------------------
 Yes No No No
Basic Scenario:

 1. Object : Account
    Fields : Phone

 2. Object : Contact
    Field  : Account(Lookup)
        MobilePhone

Scenario 6: When ever the  Account' object phone no is modified ,Its corresponding child
   contacts records mobilePhone values should be replaced with
   Account's New phoneNo

Trigger :
----------
trigger Scenario6 on Account (before update) {
List<Account> oldList=[select  id,phone,(select mobilephone from Contacts) from Account where id In: Trigger.Old];
    List<Contact> cons=new List<Contact>();
    for(Account a:oldList){
        for(Contact c:a.contacts){
          c.MobilePhone=Trigger.newMap.get(a.id).Phone;
            cons.add(c);
        }
    }
    update cons;
}

TestClass :
-----------
@isTest
private class scenario6 {
@isTest
    static void testme(){
        Account a=new Account(Name='aaa',phone='111');
        insert a;
        Contact c1=new Contact(lastname='test',mobilePhone='111',accountid=a.id);
        insert c1;
        a.phone='123';
        try{
            update a;
        }catch(Exception e){
            System.debug(e);
        }
        Account acc=[select id ,phone from Account where id=:a.id];
        Contact con=[select id,mobilePhone from Contact where Id=:c1.id];
        System.assertEquals(acc.phone,'123');
        System.assertEquals(con.MobilePhone,'123');
    }
}

Scenario 7:

Object  : Account

Fields  :Manager : Text (Create this custom Field first)

: Industry : PickList( Standard Field)

Object : User

Fields : Account_Manager : Text Fields

Task : When ever the industry field value is modified as banking then

1.Fetch the user who is the owner of the Account Record

2.Update the Account_Manager field on the user with Manager field value

Trigger:

trigger Scenario7 on Account (before update ) {
    Map<Id,Account> oldMap=Trigger.oldMap;
    Map<Id,Account> newMap=Trigger.newMap;
    List<Id> accs=new List<Id>();
    for(Id aid:oldMap.keySet()){
        if(oldMap.get(aid).Industry !=newMap.get(aid).Industry  && newMap.get(aid).Industry=='Banking'){
           accs.add(aid);
        }
    }
    List<Id> userids=new List<Id>();
    for(Id mid:accs){
        userids.add(newMap.get(mid).ownerid);
    }
    List<user> newUsers=new List<User>();
    Map<Id,User> userMap=new Map<Id,User>([select id,Account_Manager__c from User where id in :userids]);
     for(Id mid:accs){
        Id uid=newMap.get(mid).ownerid;
        User u=userMap.get(uid);
        u.Account_Manager__c=newMap.get(mid).Manager__c;
         newusers.add(u);
     }
    update  newusers;

}


Scenario 8:

Object : Account

Field : Name

Object : Contact

1.Before insert
1.When we are inserting new account record first check if there are
 any duplicate records with same name already existing

2. if they are existing throw error message

2.after update :

1. Check wheather there are any contact records already existing
  for the give account

2. if no contacts are existing create new contact


Trigger Class :

public class TriggerExample {
    public static void beforeInsert(List<Account> accs){
        List<String> names=new List<String>();
        for(Account a:accs){
            names.add(a.name);
        }
        List<Account> duplicates=[select id,name from Account where name in:names];
        if(duplicates.size()>0){
            Set<String> dupnames=new Set<String>();
            for(Account a:duplicates){
                dupNames.add(a.name);
            }
            for(Account ac:accs){
              if(dupNames.contains(ac.Name))
                    ac.addError('Duplicate name Exists');
            }
        }
    }
    public static void afterUpdate(List<Account> accs){
        List<Contact> cons=new List<Contact>();
        List<Account> accounts=[select id,name,phone,(select id from Contacts) from Account where id in:accs];
        for(Account a:accounts){
            if(a.contacts.size()==0){
                Contact c=new Contact();
                c.accountid=a.id;
                c.lastname=a.name;
                c.phone=a.phone;
                cons.add(c);
            }
        }
        insert cons;
    }

}

Trigger:
---------
trigger scenario8 on Account (before insert,after update) {
    if(Trigger.isBefore && Trigger.isInsert){
        TriggerExample.beforeInsert(Trigger.New);
    }
    if(Trigger.isAfter && Trigger.isUpdate){
        TriggerExample.afterUpdate(Trigger.New);
    }
}


Test Class :
@isTest
private class Scenario8 {
    @isTest
    static void testme(){
        Account a1=new Account(Name='aaa');
        insert a1;
        Integer count=[select count() from Account];
        Integer size=[select count() from Contact];
        Account a2=new Account(Name='aaa');
        try{
           insert a2;
        }Catch(Exception e){
          System.debug(e);
        }
Integer newCount=[select count() from Account];
         System.assertEquals(count,newCount);
        a1.phone='123';
        update a1;
        Account acc=[select id,phone from Account where phone='123'];
        System.assertEquals(acc.phone,'123');
        Integer newSize=[select count() from Contact];
        System.assertEquals(size+1,newSize);
       
    }

}
































Trigger example before and after

Trigger Class : Date 21-02-2016
=========================================================================================================
Scenario  :1
=========================================================================================================
1. Object :Opportunity

  a. When Existing Opportunity with statge name as 'Closed Won' is
     updated to any other stage it has throw error message

  b. When existing Opportunity record stageName is changed to
     closed won then  recalculate the Amount_Won for the  Correspondng Account  (Which is a sum of all closed                                                                                opportunities)

  c. When ever the stage name is changed to Closed and won
     share that opportunity record with user 'karthic'

   public class ClosedOptHandler {
     public static void beforeUpdate(Map<Id,Opportunity> oldMap,Map<Id,Opportunity> newMap){
         Set<Id> accountIds=new Set<Id>();
         for(Id a:oldMap.keySet()){
        Opportunity newOpt=newMap.get(a);
        Opportunity oldOpt=oldMap.get(a);
            if(oldOpt.stageName=='Closed Won' && newOpt.stageName!='Closed Won'){
                newOpt.addError('Stage Name cannot be updated');
            }
        }
    }
    public static void afterUpdate(Map<Id,Opportunity>oldMap,Map<Id,Opportunity> newMap){
        Set<Id> accountIds=new Set<Id>();
        for(Id a:oldMap.keySet()){
        Opportunity newOpt=newMap.get(a);
        Opportunity oldOpt=oldMap.get(a);
            if(newOpt.StageName=='Closed Won'){
                accountIds.add(newOpt.accountId);
            }
    }
    if(accountIds.size()>0){
        List<Account> accs=[select Amount_Won__c ,(select Amount from Opportunities where                                            StageName='Closed Won') from Account where Id in:accountIds ];
    Decimal sum=0;
        for(Account a:accs){
            for(Opportunity p:a.opportunities){
                sum=sum+p.amount;
            }
            a.Amount_Won__c=sum;
        }
        update accs;
    }
    }
    public static void oppShare(List<Opportunity> newOpt){
        User u=[select id from User where alias='kart'];
List<OpportunityShare> share=new List<Opportunityshare>();
    for(Opportunity op: newOpt){
        if(op.stageName=='Closed Won'){
        OpportunityShare ops=new OpportunityShare();
        ops.opportunityId=op.id;
        ops.OpportunityAccessLevel='Edit';
        ops.UserOrGroupId=u.id;
        ops.RowCause='Manual';
        share.add(ops);
        }
    }
    insert share;
    }
}

----------------------------------------------------------

Trigger :

trigger closedOppty on Opportunity (after insert,before update,after update) {
    if(Trigger.isAfter && Trigger.isInsert){
        ClosedOptHandler.oppShare(Trigger.new);
    }
    if(Trigger.isBefore && Trigger.isUpdate){
        ClosedOptHandler.beforeUpdate(Trigger.oldMap, Trigger.newMap);
    }
    if(Trigger.isAfter && Trigger.isUpdate){
        ClosedOptHandler.afterUpdate(Trigger.oldMap,Trigger.newMap);
        ClosedOptHandler.oppShare(Trigger.new);
    }
}



=======================================================================================================

Scenario 2:
========================================================================================================
Object 1: Opportunity :

Create a Custm Fields : Field Name   DataType
---------------------------------------

Total_Opportunities__c :  Number

Total_Opportunity_Amount__c : Currency


a .When  ever a new Opportunity is creatd  recalculate the  total opportunites and Total Opportunity
  amount for the corresponding Account

b. When a new Opportunity is created with out entering the account value throw error

trigger opptScope on Opportunity (before insert, after insert) {

if(Trigger.isBefore && Trigger.isInsert){

for(Opportunity opp=Trigger.new){
if(opp.accountId==null){
opp.addError('Opportuity Can not created with out AccountId');
}
}
          }
 if(Trigger.isAfter && Trigger.isInsert){

    Set<Id> accId=new Set<Id>();
    for(Opportunity op:Trigger.New){
        accId.add(op.accountId);
    }
  List<Account> accounts=[select Total_Opportunities__c,Total_Opportunity_Amount__c,
              (select id,Amount from Opportunities) from Account where Id in:accId];
    for(Account a:accounts){
        a.Total_Opportunities__c=a.opportunities.size();
        Decimal sum=0;
        for(Opportunity p:a.opportunities){
            sum=sum+p.amount;
        }
        a.Total_Opportunity_Amount__c=sum;
    }
    update accounts;
 }
}

==========================================================================================================
Scenario 3:
===========================================================================================================

Object : Contact

Custom Fields : Field Name DataType
----------------------------------------------
Source PickList: Sfdc
 SAPExternal

Account :

Custom Fields : Field Name DataType
----------------------------------------------
Source PickList: Sfdc
 SAPExternal


a. When we are trying to delete any contact record whoes source is SAP External it should throw error

b. When we trying to delete a contact whose account  source is SAP External it has to throw error



trigger conDeletes on Contact (before delete) {
    //List<Contact> cons=[select Source__c ,Account.Source__c from Contact where Id in:Trigger.Old];
    for(Contact c:Trigger.old){
        if(c.Source__c=='SAP External' || c.Account.Source__c=='SAP External'){
            c.addError('You can not delete Conatct');
        }
    }  
}









=====================================================================================================
Scenario 4:
=====================================================================================================

Object : Opportunity :

1. When ever a new Opportunity is created with Amount more than 10 lakhs  and source as 'Web'

Then add  karthic as OpportunityTeamMember

Solution :

 trigger optyTeam on Opportunity (after insert) {
    User u=[select id from User where alias='kart'];
List<OpportunityTeamMember> teams=new List<OpportunityTeamMember>();
    for(Opportunity op:Trigger.New){
        if(op.amount> 1000000 && op.LeadSource=='Web'){
            OpportunityTeamMember ot=new OpportunityTeamMember();
            ot.OpportunityId=op.id;
            ot.OpportunityAccessLevel='Edit';
            ot.userId=u.id;
            ot.TeamMemberRole='Sales Manager';
            teams.add(ot);
        }
    }
    insert teams;
}
===============================================================================================================
Scenario  5:
===========================================================================================================
Object : Opportunity

1. When ever the opportunity stage is changed create dummy record in the PipeLine object with
following fieldMaping

PipleLine__c p=new PipeLine_C

p.Stage=Opportunity_OldStage---Opportunity_NewStage

p.Days =Today()-opportunity_LastmOdifiedDate

p.Name=opportunityName



Solution :

trigger optyStageChange on Opportunity (after update) {
List<PipeLine__c> optList=new List<PipeLine__c>();
    for(Id opId:Trigger.OldMap.keySet()){
        Opportunity oldOpt=Trigger.OldMap.get(opId);
        Opportunity newOpt=Trigger.newMap.get(opId);
        if(oldOpt.stageName!=newOpt.StageName){
            PipeLine__c p=new PipeLine__c();
            p.Name=newOpt.Name;
            p.Stage__c=oldOpt.StageName+'-'+newOpt.StageName;
            Date modDate=oldOpt.LastModifiedDate.date();
            Integer days=System.Today().daysBetween(modDate);
            p.Days__C=days;
            p.ConvertedDate__c=System.today();
            optlist.add(p);
        }
    }
    insert optlist;
}

=============================================================================================================
Scenario :6
============================================================================================================

Object : Application__c

FieldName DataType Options
------------------------------------------------------
First Name Text -

Type PickList New Card
Cancel Card


Applicant PickList Business

Salaried


Status PicKList Pending
Approved
Rejected

Executive Lookup(user)

Email Email -


Object : BlackList

Field Name DataType
------------------------------------
Name Text


Object : Customer

Field Name DataType Options
-----------------------------------------------------
First Name Text

Applicatant PickList Business
Salaried



Workflow : When a new Applciation is creatd  with

Type =new Card
Status=Pending

Action : Task : Assing to the Owner

Approval : When a ever a application  is submitted for Approval


Entry Criteria : Type =New Card

Automated Approved : Submited Executives Manager

Approval steps : All Applications should enter step 1

Approval Action : Field Update Status= Approved

Rejected Action : Field Update Status ='Rejected'


 1.  When a new Application is submited for Approvel with  Application type as 'New Card'

a. check wheather Applicant name in black list object

b. If name is in the black list object Then update the status to Rejected


2. When applicant name is not in the black list submit the record for approval using trigger
and set the status as pending


3. When ever the application Status is changed to Approved

a. Create a new Customer record based on application details

Customer FirstName =Application Firstname
Customer Type =Application -ApplicantType


4.When ever the application status is rejected

a. send a email to Executive ,Executive manager, Applicant  and user with role : Verification
























































Formula examples

1. Object : Loan

   Create the fields :
---------------------------------------------------
    Field Name DataType   Options
--------------------------------------------------
    AppliedDate Date

    Type PickList Eduction
Housing
Personal

    security PicKList Asserts
Salary

    Salary Currecy

    Applied_Amount Currency

    Assert_Cost Currency
---------------------------------------------------------
Formule 1:

scenario : Create a formule field  to calculate the instalments

Education : 48
Housing   : 120
Personal  : 32


Formule : Number

CASE( Type__c ,

   'Education', 48 ,

   'Housing',120,

   'Personal',32,

    0
)

-----------------------------------------------------------
Scenario : Create a formule field to calculate intrestRate

Rule : Education : 10 %

      Housing   : 12 %

               Personal  : 14 %

Formule : Percentage

CASE ( Type__c ,

'Educaiton',0.10,

'Housing', 0.12,

'Personal',0.14,
0
)
----------------------------------------------------------------
IF( condition , stmt1, stmt2)
If the given condition is true stmt1 will execute otherwise stmt2 will be executed.

Scenario : Create a formule field  Priority

Rule : If applied amount is more than 1,00,000 then set the priority as 'High ' otherwise 'Low'

Formule :Text

IF( Applied_Amount__c > 100000 , 'High','Low')

-------------------------------------------------------------
ISPICKVAL(PickListField ,Literal) :

Scenario : Create formule field to calculate the processing fee

Loan Type  : Housing : 1000

  : other than housing : 500


Formule : Currency

IF( ISPICKVAL( Type__c,'Housing'),

     1000,

      500
)

-----------------------------------------------------------------
Scenario :  Create a formule field Max_Amount  to calcualte
maximum amount what bank can sanction

Security : Asserts

 Max Amount :60 % of assertcost

Security : Salary

 Education :  32 times of 60% of your salary

 Housing   : 100 times of 60% of your salary

 Personal  : 20 times of 60% of your salary


Formule : Currency :

IF( ISPICKVAL(Security__c,'Asserts'),

      Assert_Cost__c *0.60,

     IF( ISPICKVAL(Security__c,'Salary') ,
       
        CASE( Type__c ,

             'Education',Salary__c*0.60*32,

             'Housing',Salary__c*0.60*100,

            'Personal',Salary__c*0.60*20,

            0
        ),

        0
     )
)
=================================================================

Sceanrio : Create a formule field Sactioned Amount

Rule : If appliedAmount is less than MaxAmount amount
then  Applied Amount is Sanctioned other wise
maxamount is sanctioned

Formule :Currency


IF(  Applied_Amount__c  <  Max_Amount__c ,
       
     Applied_Amount__c,

       Max_Amount__c

)

-----------------------------------------------------------
Scenario : Create a formule field EMI

Rule :SanctionedAmount|Instalments


Formule : Currency

Sanctioned_Amount__c  / Instalments__c

-------------------------------------------------------------
Date & DateTime Functions

1. TODAY(): This will return today's date

2. Now() : Current date and time

3. DATE(YYYY,MM,DD) :This will create instance of date

DATE(2016,2,23)

4. DAY(Date) : This will return day in the month

DAY(TODAY()) : 24

DAY(DATE(2016,2,23)) : 23

5.MONTH(Date) : This will return month in the given date

MONTH(TODAY()) : 2

MONTH( DATE(2016,6,23)) : 6


6.YEAR(Date) : This will return year in the given date

YEAR(TODAY()) : 2016

7.DATEVALUE(DateTime) : This will take datetime value and
return date value

DATEVALUE(NOW()) : DATE(2016,2,24)



Scenario : Create a formule field No_Days which will return
  how many days you modified the record

 Formule : Number

 TODAY()-DATEVALUE(LastModifiedDate)

-----------------------------------------------------------------