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

How do you remove Primary Campaign Source on Opportunity if Campaign Member Responded is False
I would like to remove primary campaign source from the contact and opportunity on lead conversion unless the lead had Responded to the campaign.
I tried this trigger, but it doenst work, and i cant figure out why
trigger checkPrimaryCampaignSource on Opportunity (before update) {
for (Opportunity o: Trigger.new) {
Lead l = [SELECT id,converteddate FROM Lead WHERE ConvertedOpportunityId =:o.ID LIMIT 1];
try {
if(l.converteddate!=null){
CampaignMember cm = [Select id,Status, HasResponded FROM campaignmember WHERE LeadId=:l.id AND CampaignId=:o.Campaign.id];
if (cm.HasResponded ==false){
o.CampaignId=null;
}
}
} catch (Exception e){
system.debug('error: ' +e);
}
}
}
I tried this trigger, but it doenst work, and i cant figure out why
trigger checkPrimaryCampaignSource on Opportunity (before update) {
for (Opportunity o: Trigger.new) {
Lead l = [SELECT id,converteddate FROM Lead WHERE ConvertedOpportunityId =:o.ID LIMIT 1];
try {
if(l.converteddate!=null){
CampaignMember cm = [Select id,Status, HasResponded FROM campaignmember WHERE LeadId=:l.id AND CampaignId=:o.Campaign.id];
if (cm.HasResponded ==false){
o.CampaignId=null;
}
}
} catch (Exception e){
system.debug('error: ' +e);
}
}
}
trigger checkPrimaryCampaignSource on Lead (after update) {
//This will be a set of all opportunity IDs for leads that were just converted
Set<Id> convertedOppIds = new Set<Id>();
for (Lead l :Trigger.new) {
if (l.IsConverted == true) {
convertedOppIds.add(l.ConvertedOpportunityId);
}
}
//Now get a set of all of the campaign members related to the converted leads who have not responded to any of the campaigns
List<CampaignMember> campaignMembers = [SELECT Id, Lead.ConvertedOpportunityId FROM CampaignMember WHERE Lead.ConvertedOpportunityId IN :convertedOppIds AND HasResponded = false];
//Construct a set of opportunity ids that were converted from leads who did not respond to the campaign
Set<Id> nonResponsiveOppIds = new Set<Id>();
for (CampaignMember cm : campaignMembers) {
nonResponsiveOppIds.add(cm.Lead.ConvertedOpportunityId);
}
//Now we can get a list of all of the opportunities where we need to remove the primary campaign source
List<Opportunity> oppsToUpdate = [SELECT CampaignId FROM Opportunity WHERE Id IN :nonResponsiveOppIds];
for (Opportunity opp : oppsToUpdate) {
opp.CampaignId = null;
}
if (oppsToUpdate.size() > 0) {
update oppsToUpdate;
}
}
All Answers
Also, you should move your SOQL queries to the outside of the loop, so that you don't run into any governor limits. Here is a rough idea of what you might want to do, but keep in mind that you'll have to read the article above to stop this from firing recursively:
trigger checkPrimaryCampaignSource on Opportunity (after insert) {
//Construct a set of all campaign ids related to opportunities in the trigger
Set<Id> campaignIds = new Set<Id>();
for (Opportunity opp : trigger.new) {
campaignIds.add(opp.CampaignId);
}
//Now get a list of all of the campaign members who have not responded to any of the campaigns
CampaignMember campaignMembers = [SELECT Id, Lead.ConvertedOpportunityId FROM CampaignMember WHERE Lead.ConvertedOpportunityId IN :trigger.newMap.keySet() AND HasResponded = false];
//Construct a set of opportunity ids that were converted from leads who did not respond to the campaign
Set<Id> nonResponsiveOppIds = new Set<Id>();
for (CampaignMember cm : campaignMembers) {
nonResponsiveOppIds.add(cm.Lead.ConvertedOpportunityId);
}
//Now, go through the opportunities and update them if necessary
List<Opportunity> oppsToUpdate = new List<Opportunity>();
for (Opportunity opp : trigger.new) {
if (nonResponsiveOppIds.contains(opp.Id)) {
//trigger.new is read only, so we must make a new opportunity
Opportunity updatedOpp = new Opportuntiy(Id=opp.Id, CampaignId=null);
oppsToUpdate.add(updatedOpp);
}
}
if (oppsToUpdate.size() > 0) {
update oppsToUpdate;
}
}
List<CampaignMember> campaignMembers = [SELECT Id, Lead.ConvertedOpportunityId FROM CampaignMember WHERE Lead.ConvertedOpportunityId IN :trigger.newMap.keySet() AND HasResponded = false];
system.debug('Campaign Members ==> ' + campaignMembers);
system.debug('Non-responsive opportunity IDs ==> ' + nonResponseOppIds);
after your first for loop. Then go into Setup -> Monitoring ->Debug Logs (or Setup -> Logs -> Debug Logs if you are in the new Setup), and add a new Monitored User. Then perform an action so that your trigger runs. After that, if you refresh the debug logs page, you should see a new log corresponding to the operation you just performed. Click on View Log and find your debug statements (they should be labeled with user_debug, so you should be able to use CTRL+f in your browser to easily find them). There, you should be able to see what values your variables have and hopefully get to the bottom of what is going wrong.
28.0 APEX_CODE,DEBUG;APEX_PROFILING,INFO;CALLOUT,INFO;DB,INFO;SYSTEM,DEBUG;VALIDATION,INFO;VISUALFORCE,INFO;WORKFLOW,INFO
10:06:38.284 (284172000)|ENTERING_MANAGED_PKG|rh2
10:06:38.651 (651706000)|ENTERING_MANAGED_PKG|TRIMDA
10:06:38.809 (809749000)|ENTERING_MANAGED_PKG|TRIMDA
10:06:39.034 (1034117000)|CODE_UNIT_STARTED|[EXTERNAL]|01qZ0000000D8PP|checkPrimaryCampaignSource on Opportunity trigger event AfterInsert for [006Z0000008By3n]
10:06:39.034 (1034452000)|SYSTEM_CONSTRUCTOR_ENTRY|[3]|<init>(Integer)
10:06:39.034 (1034484000)|SYSTEM_CONSTRUCTOR_EXIT|[3]|<init>(Integer)
10:06:39.034 (1034532000)|SYSTEM_METHOD_ENTRY|[4]|LIST<Opportunity>.iterator()
10:06:39.034 (1034768000)|SYSTEM_METHOD_EXIT|[4]|LIST<Opportunity>.iterator()
10:06:39.034 (1034803000)|SYSTEM_METHOD_ENTRY|[4]|system.ListIterator.hasNext()
10:06:39.034 (1034825000)|SYSTEM_METHOD_EXIT|[4]|system.ListIterator.hasNext()
10:06:39.034 (1034928000)|SYSTEM_METHOD_ENTRY|[5]|SET<Id>.add(Object)
10:06:39.034 (1034957000)|SYSTEM_METHOD_EXIT|[5]|SET<Id>.add(Object)
10:06:39.034 (1034968000)|SYSTEM_METHOD_ENTRY|[4]|system.ListIterator.hasNext()
10:06:39.034 (1034981000)|SYSTEM_METHOD_EXIT|[4]|system.ListIterator.hasNext()
10:06:39.035 (1035110000)|SYSTEM_METHOD_ENTRY|[10]|MAP<Id,Opportunity>.keySet()
10:06:39.035 (1035165000)|SYSTEM_METHOD_EXIT|[10]|MAP<Id,Opportunity>.keySet()
10:06:39.035 (1035535000)|SOQL_EXECUTE_BEGIN|[10]|Aggregations:0|select Id, Lead.ConvertedOpportunityId from CampaignMember where (Lead.ConvertedOpportunityId = :tmpVar1 and HasResponded = false)
10:06:39.040 (1040971000)|SOQL_EXECUTE_END|[10]|Rows:0
10:06:39.041 (1041040000)|SYSTEM_CONSTRUCTOR_ENTRY|[12]|<init>(Integer)
10:06:39.041 (1041062000)|SYSTEM_CONSTRUCTOR_EXIT|[12]|<init>(Integer)
10:06:39.041 (1041083000)|SYSTEM_METHOD_ENTRY|[13]|LIST<CampaignMember>.iterator()
10:06:39.041 (1041203000)|SYSTEM_METHOD_EXIT|[13]|LIST<CampaignMember>.iterator()
10:06:39.041 (1041228000)|SYSTEM_METHOD_ENTRY|[13]|system.ListIterator.hasNext()
10:06:39.041 (1041244000)|SYSTEM_METHOD_EXIT|[13]|system.ListIterator.hasNext()
10:06:39.041 (1041262000)|SYSTEM_CONSTRUCTOR_ENTRY|[20]|<init>()
10:06:39.041 (1041277000)|SYSTEM_CONSTRUCTOR_EXIT|[20]|<init>()
10:06:39.041 (1041300000)|SYSTEM_METHOD_ENTRY|[21]|LIST<Opportunity>.iterator()
10:06:39.041 (1041319000)|SYSTEM_METHOD_EXIT|[21]|LIST<Opportunity>.iterator()
10:06:39.041 (1041328000)|SYSTEM_METHOD_ENTRY|[21]|system.ListIterator.hasNext()
10:06:39.041 (1041341000)|SYSTEM_METHOD_EXIT|[21]|system.ListIterator.hasNext()
10:06:39.041 (1041395000)|SYSTEM_METHOD_ENTRY|[22]|SET<Id>.contains(Object)
10:06:39.041 (1041419000)|SYSTEM_METHOD_EXIT|[22]|SET<Id>.contains(Object)
10:06:39.041 (1041432000)|SYSTEM_METHOD_ENTRY|[21]|system.ListIterator.hasNext()
10:06:39.041 (1041445000)|SYSTEM_METHOD_EXIT|[21]|system.ListIterator.hasNext()
10:06:39.041 (1041462000)|SYSTEM_METHOD_ENTRY|[29]|LIST<Opportunity>.size()
10:06:39.041 (1041479000)|SYSTEM_METHOD_EXIT|[29]|LIST<Opportunity>.size()
10:06:39.380 (1041497000)|CUMULATIVE_LIMIT_USAGE
10:06:39.380|LIMIT_USAGE_FOR_NS|(default)|
Number of SOQL queries: 1 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10
Number of fields describes: 0 out of 100
Number of record type describes: 0 out of 100
Number of child relationships describes: 0 out of 100
Number of picklist describes: 0 out of 100
Number of future calls: 0 out of 10
10:06:39.380|LIMIT_USAGE_FOR_NS|rh2|
Number of SOQL queries: 0 out of 100
Number of query rows: 0 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10
Number of fields describes: 0 out of 100
Number of record type describes: 0 out of 100
Number of child relationships describes: 0 out of 100
Number of picklist describes: 0 out of 100
Number of future calls: 0 out of 10
10:06:39.380|LIMIT_USAGE_FOR_NS|TRIMDA|
Number of SOQL queries: 2 out of 100
Number of query rows: 2 out of 50000
Number of SOSL queries: 0 out of 20
Number of DML statements: 0 out of 150
Number of DML rows: 0 out of 10000
Maximum CPU time: 0 out of 10000
Maximum heap size: 0 out of 6000000
Number of callouts: 0 out of 10
Number of Email Invocations: 0 out of 10
Number of fields describes: 2 out of 100
Number of record type describes: 0 out of 100
Number of child relationships describes: 0 out of 100
Number of picklist describes: 0 out of 100
Number of future calls: 0 out of 10
10:06:39.380|CUMULATIVE_LIMIT_USAGE_END
10:06:39.041 (1041578000)|CODE_UNIT_FINISHED|checkPrimaryCampaignSource on Opportunity trigger event AfterInsert for [006Z0000008By3n]
10:06:39.371 (1371418000)|ENTERING_MANAGED_PKG|leadScoring
10:06:39.433 (1433245000)|ENTERING_MANAGED_PKG|TRIMDA
trigger checkPrimaryCampaignSource on Lead (after update) {
//This will be a set of all opportunity IDs for leads that were just converted
Set<Id> convertedOppIds = new Set<Id>();
for (Lead l :Trigger.new) {
if (l.IsConverted == true) {
convertedOppIds.add(l.ConvertedOpportunityId);
}
}
//Now get a set of all of the campaign members related to the converted leads who have not responded to any of the campaigns
List<CampaignMember> campaignMembers = [SELECT Id, Lead.ConvertedOpportunityId FROM CampaignMember WHERE Lead.ConvertedOpportunityId IN :convertedOppIds AND HasResponded = false];
//Construct a set of opportunity ids that were converted from leads who did not respond to the campaign
Set<Id> nonResponsiveOppIds = new Set<Id>();
for (CampaignMember cm : campaignMembers) {
nonResponsiveOppIds.add(cm.Lead.ConvertedOpportunityId);
}
//Now we can get a list of all of the opportunities where we need to remove the primary campaign source
List<Opportunity> oppsToUpdate = [SELECT CampaignId FROM Opportunity WHERE Id IN :nonResponsiveOppIds];
for (Opportunity opp : oppsToUpdate) {
opp.CampaignId = null;
}
if (oppsToUpdate.size() > 0) {
update oppsToUpdate;
}
}
private class TestCheckPrimaryCampaignSource {
static testMethod void testCheckPrimaryCampaignSource() {
//Create Lead, Campaign, and CampaignMember
Lead l = new Lead(LastName='Test', Company='Test');
insert l;
Campaign c = new Campaign(Name='Test Campaign', IsActive=true);
insert c;
CampaignMember cm = new CampaignMember(LeadId=l.Id, CampaignId=c.Id, Status='Sent');
insert cm;
//Convert the lead
Database.LeadConvert lc = new Database.LeadConvert();
lc.setLeadId(l.id);
LeadStatus convertStatus = [SELECT Id, MasterLabel FROM LeadStatus WHERE IsConverted=true LIMIT 1];
lc.setConvertedStatus(convertStatus.MasterLabel);
Database.LeadConvertResult lcr = Database.convertLead(lc);
//Check that the new Opportunity has an empty CampaignId
Opportunity opp = [SELECT CampaignId FROM Opportunity WHERE Id = :lcr.opportunityId];
system.assertEquals(null, opp.CampaignId);
}
}
Error: System.DmlException: Update failed. First exception on row 0 with id 00Qc0000005FcihEAC; first error: CANNOT_INSERT_UPDATE_ACTIVATE_ENTITY, checkPrimaryCampaignSource: execution of AfterUpdate caused by: System.QueryException: Non-selective query against large object type (more than 100000 rows). Consider an indexed filter or contact salesforce.com about custom indexing. Even if a field is indexed a filter might still not be selective when: 1. The filter value includes null (for instance binding with a list that contains null) 2. Data skew exists whereby the number of matching rows is very large (for instance, filtering for a particular foreign key value that occurs many times) Trigger.checkPrimaryCampaignSource: line 11, column 1: [] (System Code)
I have similar requirement where in when a lead is converted, I want to set primary campaign source to be the first campaign that the lead responded to. Let's say there are three Campaigns Camp1,Camp2 and Camp3. And the lead responded to Camp2, the end result is that I am setting opportunity's campaign Id field to be this value(Camp2).Campaign Influence rule criteria has been setup as Responded= True.
So when I go to the opportunity detail page, it shows Camp2 as Primary Campaign Source, But in the campaign influence
related list on opportunity, I can see two Camp2 records.Even if i am trying to manually update primary campaign source on Opp without any trigger, its creating duplicate records.
Is there any limitation on campaign influence?