Hi Bob, that was quick! Yes this is what I am looking for. We require a contact role in our Opps, so that when things go through to our labs that they can also use the Contact Role. However people are just not scrolling down to the related lists and in many instances, not completing this section. I am an administrator, but have no clue have to do this as I have no Apex training. But always willing to learn something new...
It should be pretty straightforward. I'm assuming that by "before opporutnity is saved" you mean opportunity is closed won? As the opportunity has to be saved before you can define a contact role on it. It should be something like the following (bulkified, so should handle bulk updates/batch apex etc). There's probably the odd typo in there, just post the errors back here:
trigger trg_OppContactRoleDefined_biu on Opportunity (before update) { List<Opportunity> oppsToProcess=new List<Opportunity>();
// figure out which opportunities have transitioned to close win for (Opportunity opp: trigger.new) { // check if transitioned to closed/won, otherwise ignore if ( (opp.StageName=='Closed Won') && (trigger.oldMap.get(opp.id).StageName!='Closed Won') ) { oppsToProcess.add(opp); } }
// build a map of the count of opportunity contact role keyed by opportunity id Map<Id, Integer> ocrCountByOppId>=new Map<Id, Integer>(); List<AggregateResult> aggs=[select count(id) idCount, OpportunityId oppId from OpportunityContactRole group by OpportunityId]; for (AggregateResult ar : aggs) { ocrCountByOppId.put(ar.get('oppId'), ar.get('idCount')); }
// iterate the opportunities and for those that don't have an entry or the count is zero, add an error to stop the save for (Opportunity opp : oppsToProcess) { Integer ocrCount=ocrCountByOppId.get(opp.id); if (null==ocrCount || 0==ocrCount) { opp.addError('You must have at least one opportunity contact role to close win an opportunity'); } } }
Hi Bob, WOW! amazing, will certainly investigate this, thanks so much for your help. I would actually require this at any stage of our Opp as we may need a Lab case done before the Opp can reach the stage of "Closed Won" and when a Lab case is created our Lab guys wish to have the Contact Role. thanks Bob
Bob - our users are looking for the opportunity contact to be created upon initial creation of an opportunity. We thought of creating a new field on an opportunity that is a look-up to the contact object and when the opportunity is saved, then have a trigger to add that contact to the contact role related list. The only issue with this solution is that the users want to have an intuitive list of the possible contacts that are listed against the account the opportunity is assoicated to. Any ideas on how to solve this? We originally thought of using Lookup filters on that new field but that doesn't default show the contacts on the account, it just restrict users to searching through those contacts.
Bob - I'm getting the following error: Incompatible key type Object for MAP<Id, Integer>. What am I missing?
Map<Id, Integer> ocrCountByOppId = new Map<Id, Integer>();
List<AggregateResult> aggs = [SELECT count(id) idCount, OpportunityId oppId FROM OpportunityContactRole GROUP BY OpportunityId];
for (AggregateResult ar : aggs) {
ocrCountByOppId.put(ar.get('oppId'), ar.get('idCount'));
}
trigger trg_OppContactRoleDefined_biu on Opportunity (before update)
{
List<Opportunity> oppsToProcess=new List<Opportunity>();
// figure out which opportunities have transitioned to close win
for (Opportunity opp: trigger.new)
{
// check if transitioned to closed/won, otherwise ignore
if ( (opp.StageName=='Closed Won') && (trigger.oldMap.get(opp.id).StageName!='Closed Won') )
{
oppsToProcess.add(opp);
}
}
// build a map of the count of opportunity contact role keyed by opportunity id
Map<Id, Integer> ocrCountByOppId>=new Map<Id, Integer>();
List<AggregateResult> aggs=[select count(id) idCount, OpportunityId oppId from OpportunityContactRole group by OpportunityId];
for (AggregateResult ar : aggs)
{
ocrCountByOppId.put(ar.get('oppId'), ar.get('idCount'));
}
// iterate the opportunities and for those that don't have an entry or the count is zero, add an error to stop the save
for (Opportunity opp : oppsToProcess)
{
Integer ocrCount=ocrCountByOppId.get(opp.id);
if (null==ocrCount || 0==ocrCount)
{
opp.addError('You must have at least one opportunity contact role to close win an opportunity');
}
}
}
thanks Bob