+ Start a Discussion
tejateja 

If a checkbox field on quote is checked, i want apply the same change on all quote line items in salesforce

Consider  a checkbox field as "abc" is checked on quote, I want to apply the change to all quote line items attached to it with the same change(I have the same checkbox field on both quote and quote line items). And similarly when the checkbox is unchecked and saved, It should do the same. I observed that I can't achieve this using field updates. Can Someone help me With how I can achieve this using apex trigger.

I am attaching my trigger that I have done sofar, but it has errors, Can some one help me to get it executed. 

trigger updateabc on Quote (after insert, after update){

    QuoteLineItem ql = [select abc__c from QuoteLineItem where Quote = :trigger.new[0].id ];

    for(Quote q: trigger.new){

        if(q.abc__c == true){

            ql.abc__c = true;
        }
        if(q.abc__c == false){

            ql.abc__c = false;

        }
    }

    update ql;
}
Ramu_SFDCRamu_SFDC
Hi, I modified few things in your code as below. This should work correctly without any errors.

trigger updateabc on Quote (after insert, after update){
list<quotelineitem> qlit=new list<quotelineitem>();   
        for(Quote q: trigger.new){

qlit = [select id,abc__c from QuoteLineItem where Quoteid = :q.id ];
            list<quotelineitem> qlit1=new list<quotelineitem>();
            for(quotelineitem ql:qlit){               
             if(q.abc__c == true){
             ql.abc__c = true;
          }
          if(q.abc__c == false){
             ql.abc__c = false;
          }
                qlit1.add(ql);
               
            }
            update qlit1;
    }
}

Mark this answer as the best answer if it resolved your requirement so that it would help others who are looking out for similar solutions.
Ajay_SFDCAjay_SFDC
Hi teja , Ramu_SFDC ,

For this you have to write a bulkified trigger . Also @Rami_SFDC you should not use queries inside loop. It may hit the governor limit .

Always use collections like set , map ,list in your code 

With using collections your code will be as follows : 

trigger updateabc on Quote (after insert, after update)
{
   set<Id> quoteId = new set<Id>();
   List<QuoteLineItem> lstQuoteLineItem = new List<QuoteLineitem>();
   Map<Id,List<QuoteLineItem>> mapQuoteQuoteLItem = new Map<Id,List<QuoteLineItem>>();
  
   for(Quote objQuote : trigger.new)
   {
   quoteId.add(objQuote.Id);
   }
  
   for(QuoteLineItem objQuoteItem: [select abc__c , Quote from QuoteLineItem where Quote IN :quoteId])
   {
      if(mapQuoteQuoteLItem.contains(objQuoteItem.Quote))
        {
           List<QuoteLineItem> lstQuoteItem = mapQuoteQuoteLItem.get(objQuoteItem.Quote);
          lstQuoteItem.add(objQuoteItem);
          mapQuoteQuoteLItem.put(objQuoteItem.Quote,lstQuoteItem);
        } else
      {
         mapQuoteQuoteLItem.put(objQuoteItem.Quote , new List<QuoteLineItem> {objQuoteItem})
        }
   }
  
   for(Quote objQuote : trigger.New)
   {
    for(QuoteLineItem objItem :mapQuoteQuoteLItem.get(objQuote.Id) )
    {
         objItem.abc__c = objQuote.abc__c;
         lstQuoteLineItem.add(objItem);
    }
   }
  
   if(lstQuoteLineItem .size() > 0)
   {
      update lstQuoteLineItem;
   }
}

Happy Coding !!!! 


Mark this answer as the best answer if it resolved your requirement so that it would help others who are looking out for similar solutions.
tejateja
Hi  @ Ramu_SFDC, @Ajay_SFDC,

First of all thanks for replying to this post, 

I tried both of your codes, and also I tried to figure this out  on my own and got a working trigger that I am posting below. Ajay will this code also hit the governor limits?

I found Ramu's trigger is also working, When I tried Ajay's trigger, I got an error message : Error Error: Compile Error: Incompatible key type SOBJECT:Quote for MAP<Id,LIST<QuoteLineItem>> at line 16 column 47

My trigger:

trigger Updateabc on Quote (after Update) {

Set<Id> q1 = new Set<Id>();

for(Quote q: Trigger.new){
q1.add(q.id);
}

List<QuoteLineItem> qli = [Select abc__c from QuoteLineItem where Quote.Id in :q1];

for(Quote q2: Trigger.new){
for(QuoteLineItem qli1: qli){
qli1.abc__c = q2.abc__c;          
}
}
update qli;
}

Note : I am trying to learn, So please post a brief explanation, if possible.  And can you also post a test case along with your trigger, Thank you.


tejateja
Hi @Ramu_SFDC, @Ajay_SFDC,

Here is the test case for my trigger :

@isTest(SeeAllData=true)
public class Testupdateabc
{

     public static testMethod void updateQuoteTest()
     {
    
     Test.Starttest();
    
     Quote q = new Quote();
     q.abc__c = True;
   
    // pass value to any fields on quote which are required here  
     insert q;      // line 14 that I am getting error on.
    
     QuoteLineItem qli = new QuoteLineItem();
     qli.abc__c = True;
   
     qli.Quote.id = q.id;
     
   // pass value to any fields on quoteline item which are required here
     insert qli;
    
     qli.abc__c = False;
     update qli;
    
         Test.StopTest();

      }
 
}

But the problem is when I runtest, I am getting a error message: 

Error Message System.DmlException: Insert failed. First exception on row 0; first error: REQUIRED_FIELD_MISSING, Required fields are missing: [Name, OpportunityId]: [Name, OpportunityId]

Stack Trace Class.Testupdateabc.updateQuoteTest: line 14, column 1
Ajay_SFDCAjay_SFDC
Hi Teja ,

Give all the required and mandatory values to Quote object before inserting . Because of this your test class is failing .

Thanks ,
 Ajay