1

I have a requirement to update CampaignMember field by comparing a custom object which is not link to Campaign Member table. But the fields are same in both the objects.

My scenario is when the campaign, contact and status is added or updated in custom object, the latest entry with the status should be updated in CampaignMember table against by comparing CampaignId, ContactID and Status of Campaign Member.

The below is my code.

Trigger updateCampaignStatus on Responses__c (before update,after insert, after delete) {

    if(trigger.isinsert && trigger.isbefore && trigger.isupdate){
        map<id,Responses__c> mapcam = trigger.newmap;
        list<CampaignMember> resp = new list<CampaignMember>();

        list<CampaignMember> cam = [select id, CampaignId, Contactid, Status from CampaignMember where CampaignId in : mapcam.keyset()];

        for(CampaignMember c : cam){
            c.Status = mapcam.get(c.Id).Response_Status__c;
            resp.add(c);
            insert resp;
        }
        update resp;
    }

    if(trigger.isafter && trigger.isdelete){
        map<id,Responses__c> delres = trigger.oldmap;
        list<CampaignMember> ccc = [select id, CampaignId,Contactid, Status from CampaignMember where CampaignId in : delres.keyset()];
        delete ccc;
    }
}

But it is not updating the status of CampaignMember by comparing the CampaignID, Contact ID.

  • Hi, 1) First, you should not look in the mapcam, with the CampaignMember id, but with the CampaignMemberID, so the statement, should be: c.Status = mapcam.get(c.CampaignId).Response_Status__c; 2) Second, do NOT EVER, perform DML operations inside a loop. You will hit DML limits, pretty easily. 3) I don't understand, why do you perform an insert, than an update of all the CampaignMember records? – Endrit Sino Jun 30 '15 at 11:03
  • @EndritSino :Thanks for your quick reply. I still do not understand why the campaign member status is not updating with the Response Object status against campaign Id and Contact Id. I forget to remove the "insert". Please suggest me , how to update the campaign Member status with Response Object status against those records. – Ezhil Robert Jun 30 '15 at 11:46
  • Actually, my reply's intention was to properly structure your code, so it can be more clear what it aims to do. From what I read, I don't understand how do you want your Response_Status__c field, to be updated. Please, edit the question properly, being as clear as you can. – Endrit Sino Jun 30 '15 at 13:14
  • @Endrit Sino:Thanks for your reply. I can even explain my scenario more clearly. Responses__c is a custom object which has 3 fields, Campaign_Name__c, Contact_Name__C and Response_Status__c. There is standard table - CampaignMember. When the Response_Status__c in Responses__c is changed then Status field in Campaign Member is also should change against the Campaign and Contact specified in Response__c object. 2) No, actually we need to check whether Campaign Id and Contact Id is same in both the tables and update the Status Field with Response_Status__c value. Problem is with the relationship. – Ezhil Robert Jul 1 '15 at 5:04
1

The problem is your first if statement never becomes true so the field value changing code never gets reached. Your trigger is on before update,after insert, after delete and your condition is

if(trigger.isinsert && trigger.isbefore && trigger.isupdate)

When the trigger.isInsert is true, trigger.isUpdate is false and vice versa. So code inside it never gets reached.

Change it to if(trigger.isInsert || trigger.isUpdate). Do not use trigger.isBefore because then after insert scenario will make it false.

Also, there are a few things I like to correct in your logic code.

1) Do not have DML(insert, update etc) statements in for loops. From what I see, you are not creating new CampaignMembers, so you don't need an insert resp. You should only do the update resp

2) Is the Id of Responses__c record same as the CamapaignId of CampaignMember record?

If so, you for loop should change to

for(CampaignMember c : cam){
    c.Status = mapcam.get(c.CampaignId).Response_Status__c;
    resp.add(c);
}
update resp;

These are the problems that will prevent proper functionality of the code. We can improve the code more by not having separate list and map for Trigger.newMap and resp.

EDIT:

So with your information, I think this is what you want to achieve.

Trigger updateCampaignStatus on Responses__c (before update,after insert, after delete) {
    if(Trigger.isupdate || Trigger.isinsert){

        Map<Id, Responses__c> responsesByCampaignIds = new Map<Id, Responses__c>();
        for(Responses__c r:Trigger.new){
            responsesByCampaignIds.put(r.Campaign_Name__c, r);
        }   
        List<CampaignMember> cam = [select id, CampaignId, Contactid, Status from CampaignMember where CampaignId in : responsesByCampaignIds.keySet()];

       Responses__c resp; 
       for(CampaignMember c : cam){
            if(responsesByCampaignIds.containsKey(c.CampaignId)) {
                resp = responsesByCampaignIds.get(c.CampaignId);
                if(c.Contactid == resp.Contact_Name__c) {
                    c.Status = resp.Response_Status__c;
                }
            }
        }
        update cam;
    }
    if(trigger.isafter && trigger.isdelete){
        Map<id,Responses__c> delres = trigger.oldmap;
        List<CampaignMember> ccc = [select id, CampaignId,Contactid, Status from CampaignMember where CampaignId in : delres.keyset()];
        delete ccc;
    }
}
  • :Thanks for your reply. I can even explain my scenario more clearly. Responses__c is a custom object which has 3 fields, Campaign_Name__c, Contact_Name__C and Response_Status__c. There is standard table - CampaignMember. When the Response_Status__c in Responses__c is changed then Status field in Campaign Member is also should change against the Campaign and Contact specified in Response__c object. 2) No, actually we need to check whether Campaign Id and Contact Id is same in both the tables and update the Status Field with Response_Status__c value. Problem is with the relationship. – Ezhil Robert Jul 1 '15 at 4:59
  • Ok, few questions. 1) So are Campaign_Name__c, Contact_Name__C fields of the Responses__c record lookup fields? In other words, do those fields contain ids of Campaign and Contacts? 2) Do you want to compare both contactId and campaignId of the campaign member against responses before updating? – navD87 Jul 1 '15 at 15:37
  • 1) yes you are right, Campaign_Name__c, Contact_Name__c fields are lookup fields and contains ids of Campaign and Contact 2)Yes need to compare both CampaignId and ContactId of the Campaign Member against responses before updating. Thanks – Ezhil Robert Jul 2 '15 at 7:47
  • I have updated my answer with a sample code that should achieve what you want – navD87 Jul 2 '15 at 15:54
0

I am posting your code, revised and modified. Check the comments. If I have understood right your problem, it should work.

Trigger updateCampaignStatus on Responses__c (before update,after insert, after delete) {

// 1* Modified to properly enter the if body
if(trigger.isbefore && (trigger.isupdate || trigger.isinsert)){
    map<id,Responses__c> mapcam = trigger.newmap;        
    list<CampaignMember> cam = [select id, CampaignId, Contactid, Status from CampaignMember where CampaignId in : mapcam.keyset()];// 2* You only need this list to update Campaign Members
    // 3* Are you sure that the CampaignId points to a Response__c object ID?

    for(CampaignMember c : cam){
        c.Status = mapcam.get(c.CampaignId).Response_Status__c;
    }
    update cam;
}

/*
* 4* Still I do not understand why you want to delete all the Campaign Members, after updating them, in the previous if().
*   CampaignMembers(unless, it is your requisite).
if(trigger.isafter && trigger.isdelete){
    map<id,Responses__c> delres = trigger.oldmap;
    list<CampaignMember> ccc = [select id, CampaignId,Contactid, Status from CampaignMember where CampaignId in : delres.keyset()];
    delete ccc;
}*/

}

  • 1) if i am missing any logic then, pls help me to correct that. dont think about the code i have written. 3) There are 2 fields available one is Campaignid in Campaign members table and other is Campaign_ID in Responses__c object, as i said that there is no relationship between campaignmember table and response table. but the fields are common. so it is possible to check whether campaignid from campaignmember table and campaign_id(custom field) from reponse table is same then update the status of campaignmember? 4) Actually i need to delete the reponses after campaignmember status is updated. – Ezhil Robert Jul 1 '15 at 10:56
0

Hope this will help:

/*
*   Desc: 
*   - First you collect all the Campaign_Ids at the responses.
*   - Query all CampaignMembers, whose CampaignId is the SAME as Campaign_ID at the 
*   Responses__c object.
*   - for Loop Logic: First find out with which reponse maps this CampaignMember. Second
*   copy the value of the status. 
*/

Trigger updateCampaignStatus on Responses__c (before update,after insert, after delete) {
    if(trigger.isbefore && (trigger.isupdate || trigger.isinsert)){
        map<id,Responses__c> mapcam = trigger.newmap;     
        Map<id, id> campIdRespIdMap = new Map<id, id>();
        for(Responses__c r: mapcam.keyset()){
            campIdRespIdMap.put(r.campaign_id__c, r.id);
        }   
        list<CampaignMember> cam = [select id, CampaignId, Contactid, Status from CampaignMember where CampaignId in : campIdRespIdMap.keySet()];
        for(CampaignMember c : cam){
            id respId = campIdRespIdMap(c.CampaignId);
            c.Status = mapcam.get(respId).Response_Status__c;
        }
        update cam;
    }
    if(trigger.isafter && trigger.isdelete){
        map<id,Responses__c> delres = trigger.oldmap;
        list<CampaignMember> ccc = [select id, CampaignId,Contactid, Status from CampaignMember where CampaignId in : delres.keyset()];
        delete ccc;
    }
}`
  • Logic looks right but the first if wouldn't run for after insert. You don't need to check for before. – navD87 Jul 1 '15 at 15:39
  • @Endrit Sino HI, I am getting the below error "Error: Compile Error: Loop variable must be of type Id at line " . Here Response__c object has Campaign Id which is a custom lookup field related to Campaign. I am sure we can refer lookup because at the backup it stores the Campaign Id. Please suggest. Thanks, – Ezhil Robert Jul 2 '15 at 6:40
  • @EzhilRobert: If CampaignId is a lookup field, than I don't get it, why it goes in error. Please, check the code, because maybe I am missing something here, but the logic is right. I am sure. Taking into consideration the suggestion of navD87, you should be ok. – Endrit Sino Jul 2 '15 at 16:41
  • @EndritSino: yes it is a lookup field but it is still showing the same error. please help. – Ezhil Robert Jul 7 '15 at 6:33

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.