function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
SurekhasfdcSurekhasfdc 

Trigger-New Opportunity record to be inserted along with initial Opportunity

Hi All,
Problem:
When an Opportunity is getting inserted with amount equal or more than 50000,then create one more new opportunity with half of initial
opportunity and initial opportunity must also be updated with half of the amount.All other fields should be copied as it is to the new opportunity.
My Attempts to solve:
 I am trying to write Trigger on Opportunity object and I am able to insert the new opportunity and initial opportunity and also made 
Amount to Half in both records but the initial record is also inserted one more time.That makes the total records inserted to 3.I tried several methods like after delete,after update but not successful.My code is below the screenshot.Where am I doing mistake?please let me know.
User-added image

Trigger:
trigger OpportunityTrigger on Opportunity(before insert) {
if(Trigger.IsInsert ==True || Trigger.IsAfter==True)
{
    OppClass.secondOpp(Trigger.new);
}
 
}

Apex Class:

public class OppClass {
    public static void secondOpp(List<Opportunity> listOpp){
        if(CheckRecursive.runOnce()) {
try{
        Opportunity originalOpp=new Opportunity();
        Opportunity newOpp=new Opportunity();
        list<Opportunity> record=new list<Opportunity>();
        //System.debug('Before for loop');
       //for(Opportunity oppquery:listOpp){
          //  record=[SELECT Id,Amount from Opportunity where Amount=:newOpp.Amount];
    //    }
     //       System.debug('record from query '+record);
     //  delete record;
       
        for(Opportunity opp:listOpp){
            originalOpp.Amount=(opp.Amount)/2;
            originalOpp.Name=opp.Name;
            originalOpp.CloseDate=opp.CloseDate;
            originalOpp.StageName=opp.StageName;
            System.debug('First Opportunity '+originalOpp);
           
           
        if(opp.Amount>=50000){
           
            newOpp.Amount=(opp.Amount)/2;
            newOpp.Name=opp.Name;
            newOpp.CloseDate=opp.CloseDate;
            newOpp.StageName=opp.StageName;
           // originalOpp.Amount=25000;
        }//end of if
        }//end of for loop
        System.debug('Second Opportunity ' +newOpp);
        insert newOpp;
        insert originalOpp;
           
       
        }catch(Exception e){
            System.debug('Exception caught'+e);
        }
        }//end of recursive
    }//end of secondOpp method
}//end of class


Thanks
Surekha
Best Answer chosen by Surekhasfdc
ANUTEJANUTEJ (Salesforce Developers) 
So in before insert trigger, you will not be needing a soql to fetch the records that are being created newly you can simply access them from the trigger.new variable that holds the new records but do mind you won't be having the record id if you want to use the id then you have to go for after trigger.

Generally, before insert is used to alter the field values of the record before inserting the record and I think you are altering the amount value to be half of the entered value which comes under before insert.

I believe this below snippet that I sent earlier does this exactly:
 
Trigger:

trigger OpportunityTrigger on Opportunity(before insert) {
if(Trigger.IsInsert && Trigger.IsBefore)
{
    OppClass.secondOpp(Trigger.new);
}
 
}

Apex Class:

public class OppClass 
{
    public static void secondOpp(List<Opportunity> listOpp)
    {
        
        if(CheckRecursive.runOnce()) 
        {
        
        try
        {
        Opportunity originalOpp=new Opportunity();
        Opportunity newOpp=new Opportunity();
        list<Opportunity> record=new list<Opportunity>();
        
        for(Opportunity opp:listOpp)
        {
            opp.Amount=(opp.Amount)/2;
           
            if(opp.Amount>=50000)
            {
                newOpp.Amount=(opp.Amount)/2;
                newOpp.Name=opp.Name;
                newOpp.CloseDate=opp.CloseDate;
                newOpp.StageName=opp.StageName;
                record.add(newOpp);
            }
        }
        
        System.debug('Second Opportunity ' +newOpp);
        
        if(record.size()>0)
        {
        insert originalOpp;
         }          
        }
        catch(Exception e)
        {
            System.debug('Exception caught'+e);
        }

        }
    }
}
Can you try the above code once?
 

All Answers

ANUTEJANUTEJ (Salesforce Developers) 
Hi Surekha,

One possibility is to use before insert as you are not using id anywhere it would work fine. 

so to change above code to before insert you need to do below changes.
 
Trigger:
trigger OpportunityTrigger on Opportunity(before insert) {
if(Trigger.IsInsert && Trigger.IsBefore)
{
    OppClass.secondOpp(Trigger.new);
}
 
}

Apex Class:

public class OppClass {
    public static void secondOpp(List<Opportunity> listOpp){
        if(CheckRecursive.runOnce()) {
try{
        Opportunity originalOpp=new Opportunity();
        Opportunity newOpp=new Opportunity();
        list<Opportunity> record=new list<Opportunity>();
        //System.debug('Before for loop');
       //for(Opportunity oppquery:listOpp){
          //  record=[SELECT Id,Amount from Opportunity where Amount=:newOpp.Amount];
    //    }
     //       System.debug('record from query '+record);
     //  delete record;
       
        for(Opportunity opp:listOpp){
            originalOpp.Amount=(opp.Amount)/2;
            originalOpp.Name=opp.Name;
            originalOpp.CloseDate=opp.CloseDate;
            originalOpp.StageName=opp.StageName;
            System.debug('First Opportunity '+originalOpp);
           
           
        if(opp.Amount>=50000){
           
            newOpp.Amount=(opp.Amount)/2;
            newOpp.Name=opp.Name;
            newOpp.CloseDate=opp.CloseDate;
            newOpp.StageName=opp.StageName;
           record.add(newOpp);
        }//end of if
        }//end of for loop
        System.debug('Second Opportunity ' +newOpp);
        if(record.size()>0)
{
        insert originalOpp;
 }          
       
        }catch(Exception e){
            System.debug('Exception caught'+e);
        }
        }//end of recursive
    }//end of secondOpp method
}//end of class

Changes are highlighted in bold italic underlined.

If you are choosing to do an after update then you need to use the below changes:
 
Trigger:
trigger OpportunityTrigger on Opportunity(before insert) {
if(Trigger.IsInsert && Trigger.IsAfter)
{
    OppClass.secondOpp(Trigger.new);
}
 
}

Apex Class:

public class OppClass {
    public static void secondOpp(List<Opportunity> listOpp){
        if(CheckRecursive.runOnce()) {
try{
        Opportunity originalOpp=new Opportunity();
        Opportunity newOpp=new Opportunity();
        list<Opportunity> recordUpdate=new list<Opportunity>();
list<Opportunity> recordInsert=new list<Opportunity>();
        //System.debug('Before for loop');
       //for(Opportunity oppquery:listOpp){
          //  record=[SELECT Id,Amount from Opportunity where Amount=:newOpp.Amount];
    //    }
     //       System.debug('record from query '+record);
     //  delete record;
       
        for(Opportunity opp:listOpp){
            originalOpp.Amount=(opp.Amount)/2;
            originalOpp.Name=opp.Name;
            originalOpp.CloseDate=opp.CloseDate;
            originalOpp.StageName=opp.StageName;
recordUpdate.add(originalOpp);
            System.debug('First Opportunity '+originalOpp);
           
           
        if(opp.Amount>=50000){
           
            newOpp.Amount=(opp.Amount)/2;
            newOpp.Name=opp.Name;
            newOpp.CloseDate=opp.CloseDate;
            newOpp.StageName=opp.StageName;
recordInsert.add(originalOpp); 
           // originalOpp.Amount=25000;
        }//end of if
        }//end of for loop
        System.debug('Second Opportunity ' +newOpp);
        if(recordInsert.size()>0)
{insert recordInsert}
if(recordUpdate.size()>0)
{update recordUpdate;}           
       
        }catch(Exception e){
            System.debug('Exception caught'+e);
        }
        }//end of recursive
    }//end of secondOpp method
}//end of class

Let me know if it helps you and close your query by marking it as solved so that it can help others in the future.  

Thanks.
ANUTEJANUTEJ (Salesforce Developers) 
I would suggest going before insert as it would reduce one DML operation cost.
SurekhasfdcSurekhasfdc
Hi AnuTej,
Thank you for the quick response.Total Records inserted are 2 now :)
I am doing before insert operation as per your suggestion :) I am just sending the working code.
I appreciate your help very much.Thank you a ton!!!!


public class OppClass {
    public static void secondOpp(List<Opportunity> listOpp){
        if(CheckRecursive.runOnce()) {
    try{
        Opportunity originalOpp=new Opportunity();
        Opportunity newOpp=new Opportunity();
        list<Opportunity> record=new list<Opportunity>();
        //System.debug('Before for loop');
       for(Opportunity oppquery:listOpp){
           record=[SELECT Id,Amount from Opportunity where Amount=:newOpp.Amount];
       }

            System.debug('record from query '+record);
      // delete record;
        
        for(Opportunity opp:listOpp){
            originalOpp.Amount=(opp.Amount)/2;
            originalOpp.Name=opp.Name;
            originalOpp.CloseDate=opp.CloseDate;
            originalOpp.StageName=opp.StageName;
            System.debug('First Opportunity '+originalOpp);
            
            
        if(opp.Amount>=50000){
            
            newOpp.Amount=(opp.Amount)/2;
            newOpp.Name=opp.Name;
            newOpp.CloseDate=opp.CloseDate;
            newOpp.StageName=opp.StageName;
           // originalOpp.Amount=25000;
        }//end of if
        }//end of for loop
        System.debug('Second Opportunity ' +newOpp);
        insert newOpp;
       // insert originalOpp;
        if(record.size()>0){
            insert originalOpp;
        }    
        

        }catch(Exception e){
            System.debug('Exception caught'+e);
        }
        }//end of recursive
    }//end of secondOpp method
}//end of class
ANUTEJANUTEJ (Salesforce Developers) 
It would be much appreciated if you could close the thread by marking my answer as the best answer so that it can be useful to others in the future.
SurekhasfdcSurekhasfdc
Hi AnuTej,
I already marked as Best Answer only.I dont know why it's not showing up so..
Total 2 records are inserted but I want them to have half the Amount also.
I am still working on it.
Thanks
ANUTEJANUTEJ (Salesforce Developers) 
Can you provide an example to check the code further.
SurekhasfdcSurekhasfdc
Yeah..Sure.
I am creating new Opportunity on screen with only mandatory below values:
Opportunity Name: abc123
Amount:50000
Close date: 02/25/2021
Stage:Closed Won
I click on Save button.
2 new Opportunity Records with Amount:50000 and 25000 are created
Expected output: It has to be 2 new Opportunity Records with Amount:25000 only in both initial and new Opportunity records.
My query is not returning the records I want.I just want the ID of the initial opportunity to be passed into the query.As the record is still doesn't have RecordID(since its before insert operation),it is not running as expected.I am stuck with the latest RecordID problem.

Thanks
Surekha
 
ANUTEJANUTEJ (Salesforce Developers) 
So in before insert trigger, you will not be needing a soql to fetch the records that are being created newly you can simply access them from the trigger.new variable that holds the new records but do mind you won't be having the record id if you want to use the id then you have to go for after trigger.

Generally, before insert is used to alter the field values of the record before inserting the record and I think you are altering the amount value to be half of the entered value which comes under before insert.

I believe this below snippet that I sent earlier does this exactly:
 
Trigger:

trigger OpportunityTrigger on Opportunity(before insert) {
if(Trigger.IsInsert && Trigger.IsBefore)
{
    OppClass.secondOpp(Trigger.new);
}
 
}

Apex Class:

public class OppClass 
{
    public static void secondOpp(List<Opportunity> listOpp)
    {
        
        if(CheckRecursive.runOnce()) 
        {
        
        try
        {
        Opportunity originalOpp=new Opportunity();
        Opportunity newOpp=new Opportunity();
        list<Opportunity> record=new list<Opportunity>();
        
        for(Opportunity opp:listOpp)
        {
            opp.Amount=(opp.Amount)/2;
           
            if(opp.Amount>=50000)
            {
                newOpp.Amount=(opp.Amount)/2;
                newOpp.Name=opp.Name;
                newOpp.CloseDate=opp.CloseDate;
                newOpp.StageName=opp.StageName;
                record.add(newOpp);
            }
        }
        
        System.debug('Second Opportunity ' +newOpp);
        
        if(record.size()>0)
        {
        insert originalOpp;
         }          
        }
        catch(Exception e)
        {
            System.debug('Exception caught'+e);
        }

        }
    }
}
Can you try the above code once?
 
This was selected as the best answer
SurekhasfdcSurekhasfdc
Hi AnuTej,
You are Awesome....It is working fine now :).....I got 2 opportunity records inserted with half of the Amount entered initially...
Thank you so much for guiding me all the way through.I was trying since 2 days.
I appreciate your help :) I have marked your Answer as Best Answer.

Thanks
Surekha