0

Requirement: When an email is synced to Salesforce from Outlook, whatever Lead or Contact is associated with it needs to have the custom field Email_Opt_In__c checked. That part is working just fine. The only issue is testing the class I already created. This is the trigger that I use with the @Future Method.

   trigger TaskTrigger on Task (after insert,after update) {
    List<Lead> LList = new List<Lead>();
    List<Contact> LContact = new List<Contact>();
    Set<Id> LeadIds = new Set<Id>();
    Set<Id> ContactIds = new Set<Id>();
    Set<Id> TaskIds = new Set<Id>();
    List<Id> LeadId= new List<Id>();
    List<Id> ContId= new List<Id>();
    List<Id> TaskId= new List<Id>();


    for (Task t:Trigger.new)
    {
        if(t.whoId !=Null)
        {
          string whoid= t.whoId;          
            if (whoId.startsWith('00Q'))
            {
             LeadIds.add(t.whoId);
             TaskIds.add(t.Id);
             System.debug('Task Id in Mark:' + TaskIds);
            }
            else 
            {
             ContactIds.add(t.whoId);
             TaskIds.add(t.Id);
            }
         }
    }

    Map<Id,Lead> Leadmap = new Map<Id,Lead>([SELECT Id,Email_Opt_In__c,Email FROM Lead WHERE Id In :LeadIds]);
    Map<Id,Contact> Contactmap = new Map<Id,Contact>([SELECT Id,Email_Opt_In__c,LeadSource,Email FROM Contact WHERE Id In :ContactIds]);    

    LList=Leadmap.values();
    LContact=Contactmap.values();
    LeadId.addAll(LeadIds);
    ContId.addAll(ContactIds);
    TaskId.addAll(TaskIds);

    Util.AnalyzeTask(LeadId,ContId,TaskId);

    For (Task t: Trigger.new)
        if ( t.whoId!=Null) 
        {
          string whoid = t.whoId;
          boolean IsLead = whoid.startsWith('00Q');  
          boolean IsContact = whoid.startsWith('003');  
                    if (IsLead && (t.Type=='Phone Call' || t.Type=='Meeting'))
            {


               for (integer i=0;i<LList.size();i++)
               {
                 LList[i].Email_Opt_In__c = True;
                }

            } else
            if (IsContact && (t.Type=='Phone Call' || t.Type=='Meeting'))
            {


             for (integer i=0;i<LContact.size();i++)
              {
               LContact[i].Email_Opt_In__c = True;

              }
            }else
              if (IsContact)
              {

               for (integer i=0;i<LContact.size();i++)
               {
                if (LContact[i].LeadSource=='Broker')
                {                       
                 LContact[i].Email_Opt_In__c = True;

                }
               }
              }     
}Update LContact;Update LList;
}

And this is the @Future method:

public class Util {
    @Future
    public static void AnalyzeTask(List<Id> LeadId, List<Id> ContId,List<Id> TaskId){
    List<Lead> LList = new List<Lead>();
    List<Contact> LContact = new List<Contact>();
    Map <Id,Lead> LeadMap = new Map<Id,Lead>([SELECT Id,Email_Opt_In__c,Email FROM Lead WHERE Id In :LeadId]);   
    Map<Id,Contact> ContMap = new Map<Id,Contact>([SELECT Id,Email_Opt_In__c,LeadSource,Email FROM Contact WHERE Id In :ContId]);
    Map<Id,Task> TaskMap=new Map<Id,Task>([SELECT Id,Whoid,Type,Subject,Description from Task WHERE Id In:TaskId]);

    System.Debug('Task Id Size' + TaskId.size());

    For (Task t:TaskMap.values())
        {
         if ( t.whoId!=Null) 
        {
          string whoid = t.whoId;
          boolean IsLead = whoid.startsWith('00Q');  
          boolean IsContact = whoid.startsWith('003');  
          // Is my task an Email ?
            if (t.Type=='Email')
            {
                string subject= t.Subject;
                if (subject.startsWith('Email:'))
                    if (IsLead)
                    {
                      LList= Leadmap.values();

                      //An Email that Sync from Outlook into Salesforce.   
                      for (integer i=0;i<LList.size();i++)
                      {
                        string description = t.Description;
                        List<string> Ldesc= new List<string>();
                        Ldesc = description.split('\r\n',2);
                        System.debug('Description:' + Ldesc[0]);
                        System.debug('Leads Email:' + LList[i].Email);
                        if (Ldesc[0].contains(LList[i].Email)&& Ldesc[0].startsWith('From:'))
                        {
                         LList[i].Email_Opt_In__c = True;
                        }
                      }    
                     }  
                      else if(IsContact)
                      { System.Debug('It was a Contact:' + IsContact);
                        LContact=ContMap.values();
                        for (integer i=0;i<LContact.size();i++)
                        {
                        string description = t.Description;
                        List<string> Ldesc= new List<string>();
                        Ldesc = description.split('\r\n',2);
                        System.debug('Description:' + Ldesc[0]);
                        if (Ldesc[0].contains(LContact[i].Email)&& Ldesc[0].startsWith('From:'))
                        {
                         LContact[i].Email_Opt_In__c = True;
                        }

                        } Update LContact;     
                       }  
                      }
                }

  }
Update LList; 


    } 

}

And this is my test class:

@isTest
public class TaskTriggerTestLead {
    public static testMethod void Tasktest(){
    Lead l=sObjectCreator.createLead();
    l.Email='[email protected]';
    insert l;
    Task[] TtoCreate = new Task[]{};    
        for (integer i=0;i<200;i++){
            Task t=sObjectCreator.createTask();
            t.type='Email';
            t.Subject='Email:';
            t.Description='From:[email protected]';
            t.WhoId=l.id;
            TtoCreate.add(t);
        }
     Test.startTest();
     insert TtoCreate;
     Test.stopTest();
     update TtoCreate;   
     System.assertEquals(True,l.Email_Opt_In__c);   
    }
}

Now, if I put the Update LList in my @future method any higher, it gets inside the Loop and I run into DML statements limits. If I put the Update LList outside of the for loop, my records don't get updated.

Any help would be awesome. Thanks!

4
  • So you have tried the trigger without the testclass? Jul 22, 2015 at 14:01
  • Yeah, the trigger works, I sync an email from Outlook to Salesforce and the checkbox gets checked. I wonder if when I do LList[i].Email_Opt_In__c = True; I need to add that into the list again in the for loop before doing any insert/update outside of the loop.
    – Leo
    Jul 22, 2015 at 14:11
  • I would do it in another way. I will write it in an answer and you can try that. Jul 22, 2015 at 14:15
  • Okay, I wrote it. Jul 22, 2015 at 14:22

1 Answer 1

1

As mentioned in the comment, try this:

public class Util {
  @Future
  public static void AnalyzeTask(List < Id > LeadId, List < Id > ContId, List < Id > TaskId) {
      Set < Lead > LList = new Set < Lead > ();
      Set < Contact > LContact = new Set < Contact > ();
      Map < Id, Lead > LeadMap = new Map < Id, Lead > ([SELECT Id, Email_Opt_In__c, Email FROM Lead WHERE Id In: LeadId]);
      Map < Id, Contact > ContMap = new Map < Id, Contact > ([SELECT Id, Email_Opt_In__c, LeadSource, Email FROM Contact WHERE Id In: ContId]);
      Map < Id, Task > TaskMap = new Map < Id, Task > ([SELECT Id, Whoid, Type, Subject, Description from Task WHERE Id In: TaskId]);

      System.Debug('Task Id Size' + TaskId.size());

      For(Task t: TaskMap.values()) {
          if (t.whoId != Null) {
              string whoid = t.whoId;
              boolean IsLead = whoid.startsWith('00Q');
              boolean IsContact = whoid.startsWith('003');
              // Is my task an Email ?
              if (t.Type == 'Email') {
                  string subject = t.Subject;
                  if (subject.startsWith('Email:'))
                      if (IsLead) {
                          for (Lead currLead: Leadmap.values()) {
                              string description = t.Description;
                              List < string > Ldesc = new List < string > ();
                              Ldesc = description.split('\r\n', 2);
                              System.debug('Description:' + Ldesc[0]);
                              System.debug('Leads Email:' + currLead.Email);
                              if (Ldesc[0].contains(currLead.Email) && Ldesc[0].startsWith('From:')) {
                                  currLead.Email_Opt_In__c = True;
                                  LList.add(currLead);
                              }
                          }
                      } else if (IsContact) {
                      System.Debug('It was a Contact:' + IsContact);
                      for (Contact currContact: ContMap.values()) {
                          string description = t.Description;
                          List < string > Ldesc = new List < string > ();
                          Ldesc = description.split('\r\n', 2);
                          System.debug('Description:' + Ldesc[0]);
                          if (Ldesc[0].contains(currContact.Email) && Ldesc[0].startsWith('From:')) {
                              currContact.Email_Opt_In__c = True;
                              LContact.add(currContact);
                          }
                      }
                  }
              }
          }
    }
    Update LList;
    Update LContact;
  }
}

One tip: formatting is really important!

9
  • It didn't give me any issues when I saved it but when I ran the test it failed with this error: "Error Message System.ListException: Duplicate id in list: 003c000000dZPjaAAG" Line 50 UpdateLContact;
    – Leo
    Jul 22, 2015 at 14:27
  • Okay, easy fix: change List to Set in the beginning. Set<Lead> and Set<ContacT> Jul 22, 2015 at 14:28
  • Like this? Set < Lead > LList = new Set < Lead > (); Set < Contact > LContact = new Set < Contact > (); Now it gives me an error message in the last 2 lines Update LList; Update LContact; "DML requires SObject or SObject list type: Set<Lead>
    – Leo
    Jul 22, 2015 at 14:31
  • Yes, the difference: Set doesn't allow duplicate values Jul 22, 2015 at 14:32
  • Frederik, Thanks for all of your help! I'm not sure what to do with the "DML requires SObject or SObject list type: Set<Lead>" now. It doesn't like the Update LList; or the Update LContact;
    – Leo
    Jul 22, 2015 at 14:37

You must log in to answer this question.

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