0

I'm still new to map Usage.. How could this code be bulkified?

trigger OppyStatusCheck on Opportunity (before insert, before update) {
    for(Opportunity opp : Trigger.new) {
        if(opp.StageName=='Closed Won') {
            List<Quote> quoteChilds = [SELECT Id, Name from Quote where OpportunityId=:opp.Id and Status='Accepted'];
            if(QuoteChilds.size() < 1) {

                String errorMessage = 'At least one accepted quote required for closing an opportunity!';
                opp.addError(errorMessage);
            }
        }           
    }
}
0

You need to use the map to hold the Child Quote records outside of the loop. You can then check the map within the loop without having to utilize another SOQL query.

trigger OppyStatusCheck on Opportunity (before insert, before update) {

    map<Id,list<Quote>> opp2QuotesMap = new map<Id,list<Quote>>();

    for(Opportunity o : [Select Id, (Select, Id, Name From Quotes Where Status = 'Accepted') From Opportunity Where Id In : trigger.new]) { 
        opp2QuotesMap.put(o.Id, o.Quotes);
    }

    for(Opportunity opp : Trigger.new) {
        if(opp.StageName=='Closed Won') {
            if(opp2QuotesMap.get(o.Id).size() < 1) {

                String errorMessage = 'At least one accepted quote required for closing an opportunity!';
                opp.addError(errorMessage);
            }
        }           
    }
}
0

To 'bulkify' you would need to make the query to your Quote's outside of the main Trigger loop, I would do this:

trigger OppyStatusCheck on Opportunity (before insert, before update) {

    Map<Id,Opportunity> oppsWithQuotes = [SELECT Id, (select name from quotes where Status='Accepted') from Opportunity where Id IN :Trigger.new];

    for(Id oppId : Trigger.newMap.keySet()) {
        Opportunity opp = Trigger.newMap.get(oppId);
        if(opp.StageName=='Closed Won') {
            if(oppsWithQuotes.get(oppId).Quotes.size() < 1) {

                String errorMessage = 'At least one accepted quote required for closing an opportunity!';
                opp.addError(errorMessage);
            }
        }
    }           
}

Then, you're only hitting the DB once, getting all of the opps with accepted Quotes in the map which you can then easily count.

0

Or yet another way to do it :

trigger OppyStatusCheck on Opportunity (before insert, before update) {

    map<Id,Integer> opp2QuotesMap = new map<Id,Integer>();

    for(AggregateResult o : [Select, OpportunityID, Count(Id)cnt From Quote Where OpportunityID IN :trigger.new GROUP BY OpportunityID]) { 
        opp2QuotesMap.put((ID)o.get('OpportunityID'), (Integer)o.get('cnt'));
    }

    for(Opportunity opp : Trigger.new) {
        if(opp.StageName=='Closed Won') {
            if(opp2QuotesMap.get(o.Id) < 1) {

                String errorMessage = 'At least one accepted quote required for closing an opportunity!';
                opp.addError(errorMessage);
            }
        }           
    }

    }

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy