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
Kim AdilKim Adil 

Not sure why this trigger is creating 2 proposals instead of one

Here is the test class
global class OppPropExtension {
    WebService static string CreateProposal(string OppId) {
    
    string retVal = '';
    

    
    Opportunity Opp = new Opportunity();
    Opp = [select Proposal_Revision_Reason__c, Approved_by_Practice_Area__c, Manager_Approved__c, B_P_Resources_Required__c,
                       Opportunity_ID__c,  
                       Bid_Due__c,
                       Deal_Type__c,
                       Id,
                       LOE_Required__c,     
                       BOM_Required__c,  
                       Subcontractor__c,
                       Contract_Vehicle__c,   
                       OwnerID,
                       Practice_Area_Reported__c 
                       from Opportunity where id =:OppId] ;

    List <ProposalRequest__c> PropToInsert = new List <ProposalRequest__c> ();
    
    //for (Opportunity o : Opps) {
        
        if(
            //(Opp.Proposal_Revision_Reason__c.length() > 0 ) &&
            !String.isEmpty(Opp.Proposal_Revision_Reason__c) &&
            (Opp.Approved_by_Practice_Area__c == true)     &&
            (Opp.Manager_Approved__c == true )             
            )
            {
         
                    // check if opportunity that is being inserted meets the criteria
                    //if(Opp.B_P_Resources_Required__c == true) {
                        
                        ProposalRequest__c p = new ProposalRequest__c (); //instantiate the object to put values for future record
                        // now map opportunity fields to new proposal request
                        p.Name = Opp.Opportunity_ID__c + ':' + Opp.Deal_Type__c; 
                        p.Bid_Due__c = Opp.Bid_Due__c;
                        p.Deal_Type__c = Opp.Deal_Type__c;
                        p.Opportunity__c = Opp.Id;
                        p.LOE_Required__c = Opp.LOE_Required__c;     
                        p.BOM_Required__c = Opp.BOM_Required__c;  
                        p.Subcontractor__c = Opp.Subcontractor__c;
                        p.Contract_Vehicle__c = Opp.Contract_Vehicle__c;   
                        p.OwnerID = Opp.OwnerID;
                        p.Proposal_Revision_Reason__c = Opp.Proposal_Revision_Reason__c;
                        p.Technology_PA__c = Opp.Practice_Area_Reported__c;                      
                         //add this new object to the list that will be inserted.       
                        PropToInsert.add(p);       
                   // }
                   
                    // dml operations might cause an error, so you need to catch it with try/catch block.
                    try {
                        insert PropToInsert; 
                    } catch (system.Dmlexception e) {
                        system.debug (e);
                        return retVal;
                    }
                    
                     retVal = 'Proposal Request created successfully'; 
                     return retVal;
            
            }
            else
            {
                 retVal = 'Opportunity must be approved and revision reason selected before requesting a proposal revision'; 
                 return retVal;
            
            }      
   }  
 }

And here is the trigger 

trigger OppCreateProposalReq on Opportunity (after update) { 
    List <ProposalRequest__c> configToInsert = new List <ProposalRequest__c> ();
    
    for (Opportunity o : Trigger.new) {
        
        if(
            (o.Approved_by_Practice_Area__c == true && trigger.oldMap.get(o.id).Approved_by_Practice_Area__c == false) 
            &&
            (o.Manager_Approved__c == true && trigger.oldMap.get(o.id).Manager_Approved__c == false)
            )
            {
         
                    // check if opportunity that is being inserted meets the criteria
                    if(o.B_P_Resources_Required__c == true) {
                        
                        ProposalRequest__c p = new ProposalRequest__c (); //instantiate the object to put values for future record
                        // now map opportunity fields to new proposal request
                        p.Name = o.Opportunity_ID__c + ':' + o.Deal_Type__c; 
                        p.Bid_Due__c = o.Bid_Due__c;
                        p.Deal_Type__c = o.Deal_Type__c;
                        p.Opportunity__c = o.Id;
                        p.LOE_Required__c = o.LOE_Required__c;     
                        p.BOM_Required__c = o.BOM_Required__c;  
                        p.Subcontractor__c = o.Subcontractor__c;
                        p.Contract_Vehicle__c = o.Contract_Vehicle__c;   
                        p.OwnerID = o.OwnerID;
                        p.Proposal_Revision_Reason__c = o.Proposal_Revision_Reason__c;
                        p.Technology_PA__c = o.Practice_Area_Reported__c;                      
                         //add this new object to the list that will be inserted.       
                        configToInsert.add(p);       
                    }
            
            }
    
    //once loop is done, you need to insert new records in SF
    // dml operations might cause an error, so you need to catch it with try/catch block.
            try {
                insert configToInsert; 
            } catch (system.Dmlexception e) {
                system.debug (e);
            }
    }
}

Any help will be appreciated. Thanks
Shingo YamazakiShingo Yamazaki
Dear Kim Ch,

Sory I couldn't quite understand the relationship between OppPropExtension and trigger class.
(You saied "Here is the test class" but it's not "test" class)

Does it mean, when you call this webservice method, 2 proposals are created?
If so, since Opportunity doesn't seem to be updated, I think trigger is not executed.

And in trigger,
 
try {
    insert configToInsert; 
} catch (system.Dmlexception e) {
    system.debug (e);
}

is inside the for loop, I don't think it's good.
Amit Chaudhary 8Amit Chaudhary 8
Hi Kim Ch,

It look like your code executing two time that is why two record are created. To Resolve this issue Please follow below step
1) Create on field checkbox "ProposalRequestCreated__c" on opportunity. Defualt value should be false. And After record creation mark the value as true so that 2nd record will nt create again,
2) Then use below Trigger.
 
Please try below code:-
trigger OppCreateProposalReq on Opportunity (before update) 
{ 
    List <ProposalRequest__c> configToInsert = new List <ProposalRequest__c> ();
    for (Opportunity o : Trigger.new) 
	{
        if(
            (o.Approved_by_Practice_Area__c == true && trigger.oldMap.get(o.id).Approved_by_Practice_Area__c == false) 
            &&
            (o.Manager_Approved__c == true && trigger.oldMap.get(o.id).Manager_Approved__c == false)
            )
        {
                    // check if opportunity that is being inserted meets the criteria
                    if(o.B_P_Resources_Required__c == true && o.ProposalRequestCreated__c = false) 
					{
						o.ProposalRequestCreated__c = true;
						
                        ProposalRequest__c p = new ProposalRequest__c (); //instantiate the object to put values for future record
                        // now map opportunity fields to new proposal request
                        p.Name = o.Opportunity_ID__c + ':' + o.Deal_Type__c; 
                        p.Bid_Due__c = o.Bid_Due__c;
                        p.Deal_Type__c = o.Deal_Type__c;
                        p.Opportunity__c = o.Id;
                        p.LOE_Required__c = o.LOE_Required__c;     
                        p.BOM_Required__c = o.BOM_Required__c;  
                        p.Subcontractor__c = o.Subcontractor__c;
                        p.Contract_Vehicle__c = o.Contract_Vehicle__c;   
                        p.OwnerID = o.OwnerID;
                        p.Proposal_Revision_Reason__c = o.Proposal_Revision_Reason__c;
                        p.Technology_PA__c = o.Practice_Area_Reported__c;                      
                         //add this new object to the list that will be inserted.       
                        configToInsert.add(p);       
                    }
            
        }
    
    // once loop is done, you need to insert new records in SF
    // dml operations might cause an error, so you need to catch it with try/catch block.
            try 
			{
                insert configToInsert; 
            } catch (system.Dmlexception e) {
                system.debug (e);
            }
    }
}


Please mark this as solution if this will help you.

Thanks,
Amit Chaudhary