0

I want to track our email lists dynamically using a single-choice picklist for each email list with options of 'Subscribed' and 'Unsubscribed' that automatically assigns subscribers to a Campaign. I created a trigger that works beautifully when the specific field is named -- but I don't want to create a separate trigger for each field. Instead I want to create a for loop that iterates over the Map that holds all the relevant fields as keys and looks up CampaignId values to assign subscribers to.

The code below works on the isInsert, but fails to create a CampaignMember record in the isUpdate. The isUpdate section is necessary to avoid a duplicate error if I batch upload records, some of which already have CampaignMember records. How can I get the for loop to evaluate the Boolean expression properly? All I need is to avoid the DUPLICATE_ERROR by comparing most recent field history and check against post-update field history to make sure they weren't both 'Subscribed.'

trigger EmailSubscribe on Contact (after insert, after update) {

Map<String,String> varNameToValueMap = new Map<String,String>();
    varNameToValueMap.put('Email_List1__c','70117000000vgRA');
    varNameToValueMap.put('Email_List2__c','70117000000vgRF');

list<contact> triggerNew = Trigger.new;

for(String sub : varNameToValueMap.keySet()){
    List <Contact> ContactList = (List<Contact>) Database.query('Select Id FROM Contact WHERE ' + sub + ' = \'Subscribed\' AND Id in :triggerNew');

    List <CampaignMember> NewMembers = new List<CampaignMember>();
    if(ContactList.size() > 0){
        if(Trigger.isInsert){

        //iterate over inserted contacts and enter into previously empty list
            for (Contact l:ContactList){
                    newMembers.add(new CampaignMember(
                        ContactId = l.Id,
                        CampaignId = varNametoValueMap.get(sub),
                        Status = 'Subscribed'));
                   }
             } 

            else {
                 for(Contact c : Trigger.new) {
                     Contact con = Trigger.oldMap.get(c.Id);

                     String oldCon = 'con.' + sub + '.equals(\'Subscribed\');';
                     String newCon = 'c.' + sub + '.equals(\'Subscribed\');';

                     Boolean oldConSub = Boolean.valueOf(oldCon);
                     Boolean newConSub = Boolean.valueOf(newCon);

                    //only add updated records to list for upload if subscription field was changed from non-subscriber to subscriber 
                     if(!oldConSub && newConSub) {
                             newMembers.add(new CampaignMember(
                                     ContactId = c.Id,
                                     CampaignId = varNametoValueMap.get(sub),
                                     Status = 'Subscribed'));
                         }                      
                        }
                       }

              //upload list of subscribers to group         
              insert NewMembers;
        }
      }
     }
  • n.b. You should not hardcode IDs (campaign Ids) in the code as they won't port from sandbox to PROD - instead, query for the Campaigns using a pre-defined list of campaign names that you save in a custom setting – cropredy Jan 31 '15 at 1:16
1

You have a lot of unnecessary code in your trigger and some queries that are unneeded. For simplicity just give this a try then begin commenting on this answer se we can get what you need right

trigger EmailSubscribe on Contact (after insert, after update) {

Map<String,String> varNameToValueMap = new Map<String,String>();
    varNameToValueMap.put('Email_List1__c','70117000000vgRA');
    varNameToValueMap.put('Email_List2__c','70117000000vgRF');

list<contact> triggerNew = Trigger.new;

for(String sub : varNameToValueMap.keySet()){

    List <CampaignMember> NewMembers = new List<CampaignMember>();

    if(Trigger.isInsert){

        //iterate over inserted contacts and enter into previously empty list
        for (Contact l:trigger.new){
                if(String.valueOf(l.get(sub)) == 'Subscribed'){
                    newMembers.add(new CampaignMember(
                        ContactId = l.Id,
                        CampaignId = varNametoValueMap.get(sub),
                        Status = 'Subscribed'));
               }
            }
    } else {
         for(Contact c : Trigger.new) {

             Boolean oldConSub = string.valueOf(trigger.oldMap.get(c.id).get(sub)) == 'Subscribed';
             Boolean newConSub = string.valueOf(c.get(sub)) == 'Subscribed';

            //only add updated records to list for upload if subscription field was changed from non-subscriber to subscriber 
             if(!oldConSub && newConSub) {
                     newMembers.add(new CampaignMember(
                             ContactId = c.Id,
                             CampaignId = varNametoValueMap.get(sub),
                             Status = 'Subscribed'));
                 }                      
        }
   }

          //upload list of subscribers to group         
          insert NewMembers;

}
  • This is the original asker, I get this error: Compile Error: Method does not exist or incorrect signature: [Object].get(String) at line 28 [Boolean newConSub = string.valueOf(c.get(c.id).get(sub))] – user16795 Jan 31 '15 at 3:32
  • I think that should be : Boolean newConSub = string.valueOf(c.get(sub)) == 'Subscribed'; – Samuel De Rycke Jan 31 '15 at 10:37
  • @SamuelDeRycke - You are correct. Copy and pasted and forgot to remove the old map part of the code.... – Eric Jan 31 '15 at 15:00
  • @tkn - Updated.... – Eric Jan 31 '15 at 15:00

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.