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
David LorberDavid Lorber 

how to I a trigger to add Product2.Description to qli.Description?

I'm having trouble getting started with a basic trigger.  When a product is added to a quote, I want it to pull the product description.  Any help getting started would be appreciated

my test so far looks like:

trigger AddDescription on QuoteLineItem (before insert) {
    for (QuoteLineItem qli : Trigger.New){
        qli.Description = 'Description here';
    }
}
Best Answer chosen by David Lorber
Harish DHarish D
Hi David,

This requirement can be achieved by writing a workflow rule on the Quote Line Item object using a Field update. Write a Workflow rule on Quote Line Object and add a  Field Update with the values Field to Update = Line Item Description and Formula Value= Product2.Description.

User-added image
Mark this as Best answer if it resolves your issue.

Thanks,
Harish





 

All Answers

Harish DHarish D
Hi David,

This requirement can be achieved by writing a workflow rule on the Quote Line Item object using a Field update. Write a Workflow rule on Quote Line Object and add a  Field Update with the values Field to Update = Line Item Description and Formula Value= Product2.Description.

User-added image
Mark this as Best answer if it resolves your issue.

Thanks,
Harish





 
This was selected as the best answer
NitishNitish
Hi David,

If you want you can achieve this using the workflow Field Update as Harish has Suggested else if you want to only use trigger then you can use the below code for this.
trigger QuotelineItemDescription on QuoteLineItem (before insert) {
	
    List<String> qliParent=new List<String>();
    
    for(QuoteLineItem q:Trigger.new){
        qliParent.add(q.Product2Id);
       
    }
    
    List<Product2> pro=[SELECT Id,Description From Product2 WHERE Id in : qliParent];
    Map<Id,String> proMap=new map<Id,String>();
    
    for(Product2 p:pro){
        proMap.put(p.Id, p.Description);
    }
    
    for(QuoteLineItem ql:Trigger.new){
        if(proMap.containsKey(ql.product2Id)){
            ql.Description=proMap.get(ql.product2Id);
        }
        
    }
    
}

Thanks,
Nitish​
David LorberDavid Lorber
I think these will both work.  This gets to my bigger question.  Why would I use one instead of the other?
NitishNitish
Hi David,

As a best practice if anything is not possible with configuration then only we should go for Codes. Here we can achive this requiremnt by workflow then no need to write Apex code for this.

Thanks,
Nitish
Ajay K DubediAjay K Dubedi
Hi David, 

Below sample code can fullfill your requirements. Hope this will work for you.

trigger CopyQuoteTrigger on Opportunity (before update,before insert) {
    if(trigger.isbefore && trigger.isupdate )
    {
        CopyQuoteClass.copyOpportunityLineItemInQuote(trigger.New,trigger.oldMap);
    }
    else if(trigger.isbefore && trigger.isinsert)
    {
        CopyQuoteClass.copyOpportunityLineItemInQuoteInsert(trigger.New);
    }
}


public class CopyQuoteClass {
    
    public static void copyOpportunityLineItemInQuote(List<Opportunity> OpportunityList, Map<Id,Opportunity> idVsOpportunityMap)
    {
        try{
            List<Quote> QuoteList = new List<Quote>();
            List<OpportunityLineItem> OliList = new List<OpportunityLineItem>();
            List<QuoteLineItem> QuoteLineItemList = new List<QuoteLineItem>();
            
            Set<Id> OpportunityIdSet = new Set<Id>();
            
            for(Opportunity oppObj : opportunityList)
            {
                if(oppObj.StageName.equals('Send Quote') && oppObj.StageName!=idVsOpportunityMap.get(oppObj.id).StageName)
                {
                    OpportunityIdSet.add(oppObj.Id);
                }
            } 
            
            if(opportunityList.size()>0)
            {
                for(Opportunity opportunityObj : opportunityList)
                {
                    if(opportunityObj.StageName.equals('Send Quote') && opportunityObj.HasOpportunityLineItem == true && opportunityObj.AccountId == Null)
                    {
                        opportunityobj.addError('Please Enter Account Name');
                        
                    }
                    
                    else if(opportunityObj.StageName.equals('Send Quote') && opportunityObj.HasOpportunityLineItem == false)
                    {
                        opportunityobj.addError('Please insert The OpportunityLineItems');
                    }
                    
                    if(opportunityObj.StageName.equals('Send Quote') && opportunityObj.StageName!=idVsOpportunityMap.get(opportunityObj.id).StageName)    
                    {   
                        Quote QuoteObj = new Quote();
                        QuoteObj.OpportunityId = opportunityObj.id;
                        QuoteObj.AccountId =  opportunityObj.AccountId;  
                        QuoteObj.EffectiveDate = opportunityObj.CloseDate;
                        QuoteObj.Pricebook2Id = opportunityObj.Pricebook2Id;    
                        QuoteObj.Status = 'Draft';    
                        QuoteList.add(QuoteObj);    
                    }
                    
                    if(QuoteList.size() > 0)
                    {
                        Database.SaveResult[] QuoteSaveList = Database.insert(QuoteList);
                        system.debug('QuoteSaveList'+QuoteSaveList);
                    } 
                }
            }
            
            if(OpportunityIdSet.size()>0)
            {    
                OliList = [Select Id,Name,Quantity,OpportunityId,unitPrice,product2Id,PricebookentryId From OpportunityLineItem WHERE OpportunityId IN:OpportunityIdSet];
            }
            
            for(Quote QuotenewObj: QuoteList)
            {  
                for(OpportunityLineItem OppitemObj: OliList)
                {   
                    if(QuotenewObj.OpportunityId == OppitemObj.OpportunityId)
                    {
                        
                        QuoteLineItem QuoteLineItemNewObj = new QuoteLineItem();
                        QuoteLineItemNewObj.QuoteId = QuotenewObj.id;
                        QuoteLineItemNewObj.Quantity =  OppitemObj.Quantity;  
                        QuoteLineItemNewObj.unitPrice = OppitemObj.unitPrice;
                        QuoteLineItemNewObj.product2Id = OppitemObj.product2Id;  
                        QuoteLineItemNewObj.PricebookentryId = OppitemObj.PricebookentryId;  
                         QuoteLineItemNewObj.Description =  'Description here';
                        QuoteLineItemList.add(QuoteLineItemNewObj);
                    }   
                }     
            }
            if(QuoteLineItemList.size() > 0)
            {
                Database.SaveResult[] QuoteLineItemSaveList = Database.insert(QuoteLineItemList);
                system.debug('QuoteLineItemSaveList'+QuoteLineItemSaveList);   
            }
            
        }
        catch(Exception e)
        {
            System.debug('The following exception has occurred: ' + e.getMessage());
        }
    }  
    
    public static void copyOpportunityLineItemInQuoteInsert(List<Opportunity> OpportunityList)
    { 
        try{
            for(Opportunity opportunityNewObj : opportunityList)
            {
                if(opportunityNewObj.StageName.equals('Send Quote') && opportunityNewObj.HasOpportunityLineItem == false)
                {
                    opportunityNewObj.addError('Please insert The OpportunityLineItems');
                }
                else if(opportunityNewObj.StageName.equals('Send Quote') && opportunityNewObj.HasOpportunityLineItem == true && opportunityNewObj.AccountId == Null)
                {
                    opportunityNewObj.addError('Please Enter Account Name');
                }
            } 
        }
        catch(Exception e)
        {
            System.debug('The following exception has occurred: ' + e.getMessage());
        }
        
    }   
}


Please mark this as best answer if this solves your problem.

Thank you
Ajay Dubedi
Susan DohertySusan Doherty
Is there any way to use this, or a modified versio of this trigger, to populate the QLI description on the Add Quote Line Items interim screen, where the quantity is determined?  (The Multi-Line layout, part of the QLI Layout is what I'm referring to).  We have many parts whose part numbers are pretty nebulous without a description.  Any suggestions much appreciated.