0

I need to write a Trigger in which relationship goes like this... opportunity is the grandparent it has a child Invoice and further Invoice has a child Invoice Line which is grandChild.. what I need to do is create a field on Opportunity of text type. Now if I have an Opportunity named 'Smith' and it has related quotes named 'Q' and further quote have related QuoteLineItems named 'OLI1' and 'QLI2'... In opportunity field the name of 'Quote' should come with ':' and after that its related quoteLineItems

Smith : Qli1 , QLI2

trigger QliReport on QuoteLineItem (after insert, after update, after delete) 
{
List<Opportunity> oppList = new List<Opportunity>();
List<Quote> quoteList = new List<Quote>();
Set<Id> setId = new Set<Id>();

if(Trigger.isInsert && Trigger.isUpdate)
{
    for(QuoteLineItem qli : trigger.new)
    {
        setId.add(qli.quoteId);
        }
}

if(Trigger.isDelete)    
{
    for(QuoteLineItem qli : trigger.old)
    {
        setId.add(qli.quoteId);
        }
}



 map<Id,Quote> quoteMap = new map<Id,Quote> 
                          ([Select id, opportunityId, quote.opportunity.name, 
                             quote.opportunity.CloseDate, quote.opportunity.StageName, 
                               quote.opportunity.Id,(Select Quantity, QuoteId, Product2Id 
                                 From QuoteLineItems) From Quote Where Id IN : setId]); 

    for(quote qo : quoteMap.values())
    {
    Opportunity opp = new Opportunity();
    opp.Id = quoteMap.get(qo.Id).opportunityId
    for(Quote q : opp.quotes)
    {
        opp.Child_Details__c = opp.Child_Details__c + ':' + q.name;
        for(QuoteLineItem qli : q.QuoteLineItems )
        {
            opp.Child_Details__c = opp.Child_Details__c + ':' + qli.Quantity;
        }
    }
    oppList.add(opp);
}
upsert oppList;                          

}
8
  • 2
    So what's the issue here? Any errors? Commented Apr 14, 2016 at 8:58
  • No error is not coming now I have edited my code...But its not working
    – Anzar
    Commented Apr 14, 2016 at 9:31
  • quoteMap.get(qo.opportunityId).id this line is wrong. this should be quoteMap.get(qo.Id).opportunityId
    – Ratan Paul
    Commented Apr 14, 2016 at 9:34
  • Thanks for the reply @sfdcweb still its not working...
    – Anzar
    Commented Apr 14, 2016 at 9:59
  • @Anzar can you put debug oppList and check any record present in this list or not?
    – Ratan Paul
    Commented Apr 14, 2016 at 10:07

1 Answer 1

1
                (opportunity)
                /           \
(product2)  (quote)      (quote)   (product2)
    \         /   \           \         /
  (quotelineitem)  \        (quotelineitem)
                    \
           (quotelineitem)

Pic.1 Example of grandparent-parent-grandchild relationship

To update grandparent field with its grandchild field, we should:
1. Collect all grandchildren ids (QuoteLineItem)
2. Select all correspondent grandparents (Opportunity)
3. Reselect all grandchildren, note: deleted will now be presented
4. For each parent, calculate(concatanate) fields from grandchildren
    and place result in map <id,sObject>
    e.g. create pair (id, parent.name : grandchild1.field, grandchild2.name)
5. For each grandparent repeat similar procedure as in previous
    e.g. pair (id, grandparent.name : parent.pair1, parent.pair2)
6. Update grandparents

Example:
If we have opp with name 'US', two quotes 'California' and 'Texas' 
and three line items 'San Francisco', 'Palo Alto', 'Houston'
We ll get - > US : California : San Francisco, Palo Alto, Texas : Houston

trigger QliReport on QuoteLineItem (after insert, after update, after delete) {

Set<Id> quoteIds = new Set<Id>();   //set of all trigger related Quote ids

if ( Trigger.isInsert || Trigger.isUpdate )
    for ( QuoteLineItem qli :trigger.new )
        quoteIds.add(qli.quoteId);

if ( Trigger.isDelete )
    for ( QuoteLineItem qli :trigger.old )
        quoteIds.add(qli.quoteId);
//get all grandparents
map<id, opportunity> opportunityMap = new map <id, opportunity>([
    select id, name from opportunity where id in
        (select opportunityId from quote where id in :quoteIds)]);
//get all grandchildren for grandparents
list<QuoteLineItem> quoteLineItemList = new list <QuoteLineItem> ([
    select id, name__c, product2.name, quoteid, quote.name, quote.opportunityid 
        from QuoteLineItem where quote.opportunityid in :opportunityMap.keyset()]);
//each quoteId will refer to list of line item names
map<id,string> quoteIdToQLIFieldNameMap = new map <id,string>();

for (QuoteLineItem qli :quoteLineItemList) {
    if (quoteIdToQLIFieldNameMap.containsKey(qli.quoteId)) {
        quoteIdToQLIFieldNameMap.put(qli.quoteId, quoteIdToQLIFieldNameMap.get(qli.quoteId) + ', ' + qli.name__c );
    } else {
        quoteIdToQLIFieldNameMap.put(qli.quoteId, (qli.quote.name + ' : ' + qli.name__c));
}   }

list<Quote> quoteList = new list <Quote> ([
    select id, name, opportunityid, opportunity.name 
        from Quote where opportunityid in :opportunityMap.keyset()]);

//Repeat similar procedure, to populate map of opps 
map <id, opportunity> oppToUpdateMap = new map <id, opportunity>();

for (Quote qte :quoteList) {
    //reset Child_Details__c, if grandchildren don't exist
    if (!oppToUpdateMap.containsKey(qte.opportunityId))
        oppToUpdateMap.put(qte.opportunityId,new opportunity(id = qte.opportunityId));

    string aggrResult = quoteIdToQLIFieldNameMap.get(qte.id);
    if ( null != (aggrResult)) {
        if (!string.isBlank (oppToUpdateMap.get(qte.opportunityId).Child_Details__c)) {
             oppToUpdateMap.get(qte.opportunityId).Child_Details__c += ', ' +  aggrResult;
        } else {
             oppToUpdateMap.get(qte.opportunityId).Child_Details__c = qte.opportunity.name + ' : ' +  aggrResult;
}   }   }

//update list only if its not empty
if (!oppToUpdateMap.isEmpty())
    update oppToUpdateMap.values();
}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .