0

Okay guys, I have now spent 4 days and counting on this trigger and I really feel it shouldn't be this hard but I am having a lot of trouble trying to get it done so help would be greatly appreciated!

This is my trigger so far:

trigger ParentOppToChild on Opportunity(after update)
{
    //Get all Opportunity's with stage name = to closed won
    Set<Id> opportunityIds = new Set<Id>();
    for(Opportunity opp : Trigger.new)
    {
        if(opp.StageName == 'Closed Won' && Trigger.oldMap.get(opp.Id).StageName != 'Closed Won')
        {
            opportunityIds.add(opp.Id);
        }
    }

    // Get Opportunity Line Items
    for (Opportunity opp : [SELECT Id, (SELECT Id FROM OpportunityLineItems) FROM Opportunity WHERE Id IN :opportunityIds])
    {
        // Create grouping of opp line items by Dealership
        Map<Id, List<OpportunityLineItem>> mapDealershipItems = new Map<Id, List<OpportunityLineItem>>();
        List<OpportunityLineItem> OppLineItemsList = new List<OpportunityLineItem>();
        for (OpportunityLineItem oppLineItem : opp.OpportunityLineItems)
        { 
            mapDealershipItems.put(OppLineItem.Dealership__c, OppLineItemsList);
            If(mapDealershipItems.containsKey(oppLineItem.Dealership__c ))
            { 
                // TO-DO Check if Dealership is a key in the map
                // 1. Yes - Add opp line item to the list
                // 2. No - Add dealership (key) and new list with item inside (value)
                // 
                OppLineItemsList.add(OppLineItem);

            }
            else
            {
                OppLineItemsList.add(OppLineItem);                
               ;
            }
        }
        //mapDealershipItems.put(key, value)


        // Create opportunity and opp line items
        for (Id dealershipId : mapDealershipItems.keySet())
        {
            // TO-DO Create opportunity
            Opportunity opportunity = new Opportunity(AccountId = dealershipId,
                                                        CloseDate = Date.today(),
                                                        StageName = 'Group Contract Signed');
            try {
                insert opportunity;
            } catch (Exception e1) {

            }

            // TO-DO Create opp line items
            //  - Check checkbox in opportunity 
            List<OpportunityLineItem> oppLineItems = new List<OpportunityLineItem>();
            for(OpportunityLineItem oli : opportunity.OpportunityLineItems)
            {
                oppLineItems.add(oli);
            }

            try {
                insert oppLineItems;
            } catch (Exception e2) {

            }
        }
    }
}

I basically need to create a new opportunity (child record type) if the parent opportunity is 'closed won'. This new opportunity will have the account name set to the dealership__c(lookup field to account on OpportunityLineItem) and all the opportunity line items in its related list will be the ones related to the dealership (only the items that were associated with the dealer in the related list of the now 'closed won' parent opportunity).

I am having trouble grouping the Line Items with the Dealerships. And then trying to create the new opportunities and the line items related to it.

Again, I would be forever grateful to anyone who can help with this.

5
  • Are any of the opportunity Line items in the related list related to difference dealership__c records for a given opportunity?
    – Eric
    Aug 26, 2015 at 17:40
  • Yes they can be. So there can be dealership 1, dealership 2 each with their own related line item. Is that what you are asking?
    – Nik
    Aug 26, 2015 at 17:43
  • Just confirming: For a SINLGE opportunity, there can be multiple dealerships? Taking it further if there are two opportunities in the trigger and each opportunity has a OLI for dealership 1 and Dealership 2, how many Opportunities will be created? (1 for each dealership for a total of 2 each with 2 OLI's, or 4, each with a single OLI)
    – Eric
    Aug 26, 2015 at 17:47
  • Yes so for example there is one opportunity (Parent). You go down to the list of Line Items. There you see some products with values for fields such as quantity, ratecard, discount, sales price, total price, date and then there is a field for Dealership. That is the dealership associated with that item. 2 would be created as I am trying to get all the line items associated with the dealership and based on that create a new opportunity which will have those related line items in the related list of that newly created opportunity. Is this making sense or am I confusing you?
    – Nik
    Aug 26, 2015 at 17:55
  • You have to take into account that there may be up to 200 opportunities in the trigger. So the question is how to handle OLI's across multiple Opportunities with the same value for Dealership__c. In my answer below, I create one Opp for the dealership__c and add ALL OLI's across ALL opportunities (and thus OLI's) in the trigger for a given Dealership__c value
    – Eric
    Aug 26, 2015 at 18:04

2 Answers 2

1

You will have to do some basic debugging as I did not try and compile the code. Hopefully with the comments it makes sense and you can add to it

You will have to add a recursion check as you will be inserting new Opportunities.

Disclaimer: this is not a "best practice" code sample but a quick workup.

Recursion Check

public class checkRecursion{

    public static boolean stopOpportunity = false;

}

Trigger

trigger ParentOppToChild on Opportunity(after update)
{
    //Check recursion and do not run if this trigger is alredy running
    if(checkRecursion.stopOpportunity) return;

    //Get all Opportunity's with stage name = to closed won
    Set<Id> opportunityIds = new Set<Id>();
    for(Opportunity opp : Trigger.new)
    {
        if(opp.StageName == 'Closed Won' && Trigger.oldMap.get(opp.Id).StageName != 'Closed Won')
        {
            opportunityIds.add(opp.Id);
        }
    }

    Opportunity[] toProcess = [SELECT Id, (SELECT Id, Dealership__c FROM OpportunityLineItems Where Dealership__c != null) FROM Opportunity WHERE Id IN :opportunityIds];

    //Create a map of the Dealerships to ALL Opps with Line Items having a Dealership__c value
    Map<ID, Opportunity> mapOppDealership = New Map<ID,Opportunity>();

for(Opportunity opp : toProcess){
    for (OpportunityLineItem oppLineItem : opp.OpportunityLineItems){
        //dealership__c is the Key since we are aggregating by Dealership
        Opportunity tmp = mapOppDealership.get(oppLineItem.Dealership__c);

        if(tmp == null){ //No Opp created yet so create it by cloning the opp
            //Create a Opp for that dealership
            Opportunity new_opp = new Opportunity(
                                                    AccountId = oppLineItem.dealership__c,
                                                    CloseDate = Date.today(),
                                                    StageName = 'Group Contract Signed'                
                                                );
            mapOppDealership.put(oppLineItem.Dealership__c,new_Opp);
        }
    }  
}

    checkRecursion.stopOpportunity = true; //ensure this trigger does not run again due to WFR or RUS
    insert mapOppDealership.values();

    //List of Opp Line Items to insert
    List<OpportunityLineItem> mapDealershipItems = new List<OpportunityLineItem>();

    // Create Opportunity Line Items
    for (Opportunity opp : toProcess)
    {
        //For each Opportunity line item in the original trigger
        //Clone it and attach it to the Opportunity created eairlier using the Dealership__c as the Key
        //if no opp was created ignore the OLI

        for (OpportunityLineItem oppLineItem : opp.OpportunityLineItems)
        { 
            if(mapOppDealership.containsKey(OppLineItem.Dealership__c)){
                OpportunityLineItem tmp = OppLineItem.clone(false,true); //Clone the line item
                tmp.OpportunityID = mapOppDealership.get(OppLineItem.Dealership__c); //reparent

                mapDealershipItems.add(tmp); //add to list
            }
        }
    }

    insert mapDealershipItems;

}

This trigger will go through the Opp Line Items and create an opportunity for each dealership (Across ALL Opportunity Line Items in the trigger)

Then it will go through them again and create new line items, attaching them to the Opportunities created above.

Basically it aggregates all records in the trigger by dealership.

4
  • Thanks for your effort Eric I really appreciate you going through this code. I am getting an error with the recursion check though. Error:Variable does not exist: checkRecursion.stopOpportunity
    – Nik
    Aug 26, 2015 at 18:10
  • Again, Basic debugging as I wrote it quickly. Also, I update the code several times in the last few minutes. Try now with the new code
    – Eric
    Aug 26, 2015 at 18:12
  • Thanks Eric I will go through this code and see what I can come up with. I will revisit this question and update on how I get on. Thanks again!
    – Nik
    Aug 26, 2015 at 18:17
  • @Nik - Did you get this working?
    – Eric
    Aug 27, 2015 at 3:31
0

below code is to create the Map of DealershipID with OpportunityLineItems. Thanks.

// Code to create the map of Dealership__c ( Account) and OpportunityLineitems. 

Map<Id, List<OpportunityLineItem>> mapDealershipItems = new Map<Id, List<OpportunityLineItem>>();
for (OpportunityLineItem oppLineItem : opp.OpportunityLineItems){ 
             if ( ! mapDealershipItems.Containskey(oppLineItem.Dealership__c))
                     mapDealershipItems.put(oppLineItem.Dealership__c,new list <OpportunityLineItem>)
                mapDealershipItems.get(oppLineItem.Dealership__c).add(oppLineItem); 

        }

  system.debug('Map of Dealership with OpportunityLineitems ' + mapDealershipItems) ;     // it will map of Dealership Id with the OpportunitylineItems

You must log in to answer this question.

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