function readOnly(count){ }
Starting November 20, the site will be set to read-only. On December 4, 2023,
forum discussions will move to the Trailblazer Community.
+ Start a Discussion
Raj R.Raj R. 

How to create a one to many relationship between a campaign and campaign members?

Hi,
How can i create a one to many relationship between a campaign and campaign members? The setup is as follows: whenever a lead or contact is added to a campaign, it is considered a campaign member. I want to be able to check if a particular lead or contact is a campaign member already. If not, then I want to make it a campaign member of a campaign when a certain criteria is met.

how can I do this in an apex class/trigger?
Best Answer chosen by Raj R.
Ashish_SFDCAshish_SFDC
Hi , 


Try the below code, 

trigger doStuff on Child__c (after insert, after update, after delete, after undelete) {

Set<String> accIdsSet = new Set<String>();
if (trigger.isInsert || trigger.isUpdate || trigger.isUndelete) {
  for (Child__c c: trigger.new) {
   if (c.Type__c != null) accIdsSet.add(c.Account__c);
  }
}

if (trigger.isDelete) {
  // we use old cause after delete new is not accesible
  for (Child__c c: trigger.old) {
   if (c.Type__c != null) accIdsSet.add(c.Account__c);
  }
}

Map<Id, Account> accMap = new Map<Id, Account>([SELECT Id FROM Account WHERE Id IN:accIdsSet]);
List<Child__c> childrenList = [SELECT Id, Type__c, Account__c FROM Child__c WHERE Account__c IN:accIdsSet AND Type__c!=null];

List<Account> updatedAccList = new List<Account>();
Map<Id, List<Child>> accIdToChildrenList = new Map<Id, List<Child>>();
for (Child__c c: childrenList) {
  if (accIdToChildrenList.get(c.Account__c) == null) {
   List<Child__c> cList = new List<Child__c>();
   cList.add(c);
   accIdToChildrenList.put(c.Account__c, cList);
  } else {
   accIdToChildrenList.get(c.Account__c).add(c);
  }
}

for (Id accId: accIdToChildrenList.keyset()) {
  Decimal sum = 0;
  String foundTypes = '';

  for (Child__c c: accIdToChildrenList.get(accId)) {
   if (!foundTypes.contains(c.Type__c)) {
    sum += 10;
    foundTypes += c.Type__c;
   }
  }

  Account acc = accMap.get(accId);
  acc.Rollup_of_10s_c = sum;

  updatedAccList.add(acc);
}

System.debug('updatedAccList has this value: ' + updatedAccList);
update updatedAccList;
}

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers.htm
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables_considerations.htm

Also See the related threads below, 

https://developer.salesforce.com/forums/ForumsMain?id=906F00000009OnNIAU

https://developer.salesforce.com/forums/ForumsMain?id=906F000000094FyIAI


Regards,
Ashish

All Answers

Ashish_SFDCAshish_SFDC
Hi , 


Try the below code, 

trigger doStuff on Child__c (after insert, after update, after delete, after undelete) {

Set<String> accIdsSet = new Set<String>();
if (trigger.isInsert || trigger.isUpdate || trigger.isUndelete) {
  for (Child__c c: trigger.new) {
   if (c.Type__c != null) accIdsSet.add(c.Account__c);
  }
}

if (trigger.isDelete) {
  // we use old cause after delete new is not accesible
  for (Child__c c: trigger.old) {
   if (c.Type__c != null) accIdsSet.add(c.Account__c);
  }
}

Map<Id, Account> accMap = new Map<Id, Account>([SELECT Id FROM Account WHERE Id IN:accIdsSet]);
List<Child__c> childrenList = [SELECT Id, Type__c, Account__c FROM Child__c WHERE Account__c IN:accIdsSet AND Type__c!=null];

List<Account> updatedAccList = new List<Account>();
Map<Id, List<Child>> accIdToChildrenList = new Map<Id, List<Child>>();
for (Child__c c: childrenList) {
  if (accIdToChildrenList.get(c.Account__c) == null) {
   List<Child__c> cList = new List<Child__c>();
   cList.add(c);
   accIdToChildrenList.put(c.Account__c, cList);
  } else {
   accIdToChildrenList.get(c.Account__c).add(c);
  }
}

for (Id accId: accIdToChildrenList.keyset()) {
  Decimal sum = 0;
  String foundTypes = '';

  for (Child__c c: accIdToChildrenList.get(accId)) {
   if (!foundTypes.contains(c.Type__c)) {
    sum += 10;
    foundTypes += c.Type__c;
   }
  }

  Account acc = accMap.get(accId);
  acc.Rollup_of_10s_c = sum;

  updatedAccList.add(acc);
}

System.debug('updatedAccList has this value: ' + updatedAccList);
update updatedAccList;
}

http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers.htm
http://www.salesforce.com/us/developer/docs/apexcode/Content/apex_triggers_context_variables_considerations.htm

Also See the related threads below, 

https://developer.salesforce.com/forums/ForumsMain?id=906F00000009OnNIAU

https://developer.salesforce.com/forums/ForumsMain?id=906F000000094FyIAI


Regards,
Ashish
This was selected as the best answer
Dominic Blythe 18Dominic Blythe 18
There's already a one to many relationship between a Campaign and Campaign Members. One Campaign has many Campaign Members.

Do you mean that when a Contact or Lead is added to a Campaign,  you want it to also be added to some other Campaign (based on criteria) ?
Raj R.Raj R.
Dominic - My situation is as follows: There is a one to many relationship between a campaign and campaign members. I want to check if the new lead/contact that got created is already a campaign member (the lead/contact could also already be in the system it does not necessarily have to be new) of a particular campaign. If the lead/contact is not a campaign member, then based on a criteria, I want to add  the lead/contact to the campaign (by adding to the campaign the lead/contact becomes a campaign member). My question was how can i utilize an apex class or trigger to check if a lead/contact is already a campaign member and if it is not, then i should add it to the campaign based on a criteria. 

Ashish - Thanks for the excellent example. i will look into the logic behind it and see how i can implement this. I appreciate the effort in showing me an example. 
Apoorv Jain 4Apoorv Jain 4
Hi, I am new to apex my query is:
I am iterating a list of campaign members List<CampaignMember> campaignMemberList = [select id,CampaignID,ContactId,LeadID,Status from CampaignMember where CampaignID =: newCampaign.Id];
and i want to fetch only active contacts(there is a field on contact object Employee_Status__c), So while iterating the above list i need to fetch active contact :
 List<CampaignMember> campaignMemberList = [select id,CampaignID,ContactId,LeadID,Status from CampaignMember where CampaignID =: newCampaign.Id];
        List<CampaignMember> newCampaignMemberList = new  List<CampaignMember>();
        if(campaignMemberList.size() >0){
            for(CampaignMember cmp : campaignMemberList){
                CampaignMember cmpNew = new CampaignMember();
                cmpNew.CampaignID = Camp.ID;
                cmpnew.ContactId = cmp.ContactId;
                cmpnew.LeadID = cmp.LeadID;
                cmpnew.Status = cmp.Status;
                //** Copy all fields data into new campaign member records. **
                newCampaignMemberList.add(cmpNew);
            }
            insert newCampaignMemberList;
        }