You need to sign in to do that
Don't have an account?

Apex trigger for OpportunityContactRole object
Hi experts,
I found a Salesforce object named OpportunityContactRole by using the IDE (Eclipse) and I want to add a new trigger for this object but I got the following Error message when try to save the new created trigger:
Save error: SObject type does not allow triggers: OpportunityContactRole
I really need to add the special processing to this object before updating, do any experts have any idea how to fix this issue?
Best regards!
Boi Hue
Message Edited by boihue on 12-09-2008 11:02 AM
Message Edited by boihue on 12-09-2008 11:02 AM
This is not real time, and I bet you want real time updates.
I thought maybe the opportunity was updated when you add a contact role record but it's not.
Anyone else have an idea?
Hi,
It's impossible to create the trigger for OpportunityContactRole object, and even the Opportunity's trigger has not been fired when Contact Roles are inserted or updated. I found that there're too much limit in Salesforce system (Governors limit, junction tables...).
Regards!
Hey,
I have the same problem here. I'm debugging, and when I update the contact roles for an oppty it does not make any API call...
:smileysurprised:
So, the oppty trigger is not fired and the OpportunityContactRole insert is done in the "background"????
Anyone? any ideas on this?
Thanks in advance!
Was anyone able to find a solution to this problem?
Thanks.
Here's a (possibly known) trick to detect such a change using Visualforce and native Opportunity layouts. It's really about having your code "know" (and possibly execute) every time a user visits a native Salesforce layout (regardless of the object.) Hence, we could call it an "On-View" trigger.
Write a very simple Apex controller that has a constructor and one method with a future annotation. The future annotation will ensure there's no lack time when the page is loaded due to the "hidden" Apex processing you'll be doing:
Then write a very simple Visualforce page that uses the "action" attribute in the apex:page markup:
Add the Visualforce page to any/all Opportunity layouts with width and height settings set to zero.
Everytime the user navigates to an Opportunity layout the code will execute. Given that the only way a user can make a change to Opportunity Contact Roles is through some sort of "native" Opportunity layout, you're ensured that this will trigger for every such change. (The exception being if you're org already has some custom Apex/VF that allows/makes changes to Opportunity Contact Roles… in which case you could do the appropriate rollup/scoring etc.. within that.) Just to be clear, if a user makes a change to Opportunity Contact Roles, after clicking save, Salesforce brings the user back to the Opportunity layout by default,, so your code will execute again with the freshest Opportunity Contact Role data.
Lastly, it should be noted that using the future annotation means it won't be totally real time… but more so than a cron job and as mentioned earlier, the page will load without delay.
Happy clouds ~~~
Ingenious solution. And with knowledge of this work-around, (which fires (translation - spins server cpu cycles) on Opportunity display whether or not OCR's were touched, viewed, or not), Salesforce should drop the restriction, and allow the creation of triggers against the OCR object itself. :)
Pete
(What if we said PLEASE?)
I already set up a class "ApexDailyJobs" which I scheduled to just execute daily and tehere I can just add in any additional processing that needs to be done daily. I guess I could just add in an OCR processing, oh well...
@Tbom:
This is a very cool trick indeed! +1 for that one. I just fear that this piece of code will be executed so often that it may eat quite some calls...
PS: Recently I happen to install Rollup Helper app and it generated error saying "SObject type does not allow triggers: OpportunityContactRole.
Can you please explain the situation like what is the field in contact 'Some_field__c ' and it is assigned to opportunity finally.may i know the field and exact assignment.I have this requirement in out development.please help me on this.
Thanks,
Krishna.
It will be good to have Contact Role exposed to triggers, but there are three solutions, I can think:
1. Scheduling a script to run every day to update count field on the opportunity. (I recommend this solution).
2. creating a small VF, and adding it on the detail page of the opportunity (it will not be visible just like a VF we removed a few weeks ago), so when the opportunity detail page is opened it will count the contact roles of that opportunity and update it if changed [it will work instantly but it will require the detail page to load for once], opportunities which are not visited will be untouched.
3. Adding logic to opportunity trigger so every time an opportunity is edited, it will query on OpportunityContactRole to roll up (personally I do not recommend this).
Best,
Jatin Narula
I am just curious why Jatin doesnt think adding logic on the opportunity trigger is a good solution? Thanks !
The problem with jatin's solution 3. with an Opportunity trigger is that in case an opportunity is edited normally, e.g. changing the stage from Prospect to Closed Won, will cause a recalculation of the Opportunity Contact Roles even though it was not necessary as the roles were not changed. That means you do A LOT more useless recalculation than actually useful ones. Plus, a change in an Opportunity Contact Role does not necessarily cause an update on the Opportunity. Thus if you ONLY change the Opportunity Contact Role but nothing on the Opportunity, you will have wrong data.
Option 1. with a daily script is much better because you will with 100% security only update Opportunities of which the Opportunity Contact Roles have changed. The only drawback of this is, it is not real time. Usually one programs these scripts to run in the night.
@Jatin
Just thought about this: Your method 1. is unsecure when it's about deleting opportunity contact roles unless you include deleted records in your query.
I actually think it should query deleted records. Otherwise how would you recognise that one Opportunity Contact Role got deleted? If you don't your count will still show the old value.
List<Opportunity> oppsToUpdate = new List<Opportunity>();
for(Opportunity each : [SELECT Id, Count__c, (SELECT Id FROM OpportunityContactRoles) FROM Opportunity]){
Integer roleCount = each.OpportunityContactRoles.size();
if(roleCount != each.Count__c){
Count__c = each.OpportunityContactRoles.size();
oppsToUpdate.add(each);
}
}
if(!oppsToUpdate.isEmpty()) Database.update(oppsToUpdate, false);
While this indeed works as you state, it is not viable for large organisations with hundreds of thousands of Opportunities. Basically you check your entire company's worth of Opportunity data every day.
I just made another check but it seems like this is the best we can achieve, since delete OCRs don't wander into the Recycle Bin and thus are not queriable with ALL ROWS.
The solution proposed is to pass as an argument to the method below the opportunities that change stage to: Closed Won. But im wondering if I could be able to, every time an opportunityContactRole is edited, to pass the Opportunity that is related to it, as the argument of the enforceContactRoleValidation() (see code below) ?
"This is a static method that you can place in a utility class separate from your Opportunity Trigger. You can pass in some arguments, such as the Contact Role you are checking for, and the message you want displayed to the user if the Contact Role is not found. In this way, the method is a little more reusable in case your requirements change in the future.
In your Opportunity trigger, you would first build a map of all Opportunities that have changed to the "Closed Won" stage as a part of the current transaction. Using that map, you can call this method below from your utility class and pass in the list of Opportunity Ids, the Opportunities themselves, as well as the Contact Role and the Error Message text. The method will do the rest!
I hope this is helpful! If so, please like and mark this answer as the best answer at your convenience, and as always, let us know if you need anything else! :) "
Thankyou all for your help!!