0

I have a working trigger on CampaignMember that will update an "Events Attended" field on Contact whenever they are added to a campaign. I want to go one step further and limit it to only count towards this field, if the Campaign they are added to is a certain Campaign Record Type. Essentially a custom rollup count field.

trigger CMTrigger on CampaignMember (after insert, after update, after delete, after undelete) {
 
Set<Id> contactIds = new Set<Id>();

if(trigger.isInsert || trigger.isUpdate || trigger.isUndelete){
    for(CampaignMember cm:trigger.new){
        if(cm.ContactId != null && cm.Campaign.RecordTypeId == '012610000006vXKAAY'){
            contactIds.add(cm.ContactId);
        }
    }
}
 
if(trigger.isUpdate || trigger.isDelete){
    for(CampaignMember cm:trigger.old){
        if(cm.ContactId != null && cm.Campaign.RecordTypeId == '012610000006vXKAAY'){
            contactIds.add(cm.ContactId);
        }
    }
}
 
if(!contactIds.isEmpty()){
    List<Contact> conList = [SELECT Id, Events_Attended__c, (SELECT Id FROM CampaignMembers) 
                             FROM Contact WHERE Id IN : contactIds];
    if(!conList.isEmpty()){
        List<Contact> updateConList = new List<Contact>();
        for(Contact con:conList){
            Contact objCon = new Contact(Id = con.Id, Events_Attended__c = con.CampaignMembers.size());
            updateConList.add(objCon);
        }
        if(!updateConList.isEmpty()){
            update updateConList;
        }
    }
}

}

When I added the

if(cm.ContactId != null && cm.Campaign.RecordTypeId == '012610000006vXKAAY')

The && and following logic into my if statements the trigger no longer counts any campaigns. I am not thrown any errors though. I have also tried to use a different field on Campaign to signify to count or not count, and it still passes over i.e. made a count__c field that I called the same way. I think it is something easy I am missing, but cannot figure it out. My indents are right, but messed up when pasting the code block.

2 Answers 2

0

When all you need is a count, it's best to not count individual records if you can help it, and you should prefer to use the query to filter out irrelevant results. As a simple fix, you could have:

List<Contact> conList = [SELECT Id, Events_Attended__c, (SELECT Id FROM CampaignMembers WHERE Campaign.RecordType.Name = 'ABC') 
                         FROM Contact WHERE Id IN : contactIds];

Presto, you no longer have to use the IF statement. This is both faster and less code, so there's no reason not to use it. However, all of this stuff was way too complicated. You could have simply:

Map<Id, Contact> contacts = new Map<Id, Contact>();
if(Trigger.new != null) {
  for(CampaignMember member: Trigger.new) {
    contacts.put(record.ContactId, new Contact(Id=record.ContactId, Events_Attended__c=0));
  }
}
if(Trigger.old != null) {
  for(CampaignMember member: Trigger.old) {
    contacts.put(record.ContactId, new Contact(Id=record.ContactId, Events_Attended__c=0));
  }
}
contacts.remove(null);
for(AggregateResult result: [SELECT Count(Id) sum, ContactId contactId FROM CampaignMember WHERE ContactId = :contacts.keySet() AND Campaign.RecordType.Name = 'ABC' GROUP BY ContactId]) {
  contacts.get((Id)result.get('contactId')).Events_Attended__c = (Integer)result.get('sum');
}
update contacts.values();

This covers all possible scenarios you can imagine in a lot less code. Also note the use of RecordType.Name to avoid using an ID, which may be different in different orgs.

1
  • Thank you. This is definitely a much cleaner version of my code.
    – Reed
    Commented Aug 7, 2020 at 14:22
0

Your query is not retrieving any results because the Campaign Record Type Id will be null if you do not query it itself.

Please find this blog post which explains this in detail.

Best regards!

1
  • Thanks for resource. Helped out a lot. Was so zeroed in on the if statements that I forgot about my query.
    – Reed
    Commented Aug 7, 2020 at 14:24

You must log in to answer this question.

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