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
Gwirizanani SinoiaGwirizanani Sinoia 

Compare Multiple Values In a Trigger

Hi All, Please help!

I have the following scenario of at least four email address field on one object called Students
  1. Email1
  2. Email2
  3. Email3
  4. Email4
All with a LastModified date that captures the date on update of that particular email address. Please note the fields are named after the parent email address.On the following fields:
  1. Email1Date
  2. Email2Date
  3. Email3Date
  4. Email4Date
Formula fields to caculate the number of days the email was modified or created from today.Please note days are name after the parent date
  1. Email1Days
  2. Email2Days
  3. Email3Days
  4. Email4Days
A primary email address field:
  1. PrimaryEmail

The objective is to create a trigger that will loop through the number of days and find the lowest and then populate the Primary email address with a corresponding address. This  lowest number of days will mean the email is current therefore populate the primary address. However  the logic  should  also be able to  take into consideration when one or more number of days fields are blank. Please note they is always one or more addresses all the time. The logic should also exempt users who manually update the Primary email address field.

Many Thanks 


 
Best Answer chosen by Gwirizanani Sinoia
Abdul KhatriAbdul Khatri
Sorry for the hassle but here is the complete solution with the Test class (coverage = 100%)

Trigger
trigger UpdateStudentPrimaryEmail on Students__c (before Insert, before update) {
    
    for(Students__c studentRec : trigger.new){
        
        studentRec.PrimaryEmail__c =  StudentsService.getPrimaryEmail(studentRec);
        
    }    
}

Class
public class StudentsService {

    public static String getPrimaryEmail (Students__c student) {
    
        Map<String, Date> emailDateMap = new Map<String, Date>();
        String primaryEmailReturn;
        
        if(student.Email1__c != null) 
            emailDateMap.put(student.Email1__c, student.Email1Date__c);
        
        if(student.Email2__c != null && student.Email2Days__c != null) 
            emailDateMap.put(student.Email2__c, student.Email2Date__c);
        
        if(student.Email3__c != null && student.Email3Days__c != null) 
            emailDateMap.put(student.Email3__c, student.Email3Date__c);
        
        if(student.Email4__c != null && student.Email4Days__c != null) 
            emailDateMap.put(student.Email4__c, student.Email4Date__c);
        
        if(emailDateMap.isEmpty()) return null;
    
        Date emailLastModifiedDate;    
        for(string email : emailDateMap.keySet()) {
            if(emailLastModifiedDate == null || emailDateMap.get(email) > emailLastModifiedDate) {
                primaryEmailReturn = email;
                emailLastModifiedDate = emailDateMap.get(email);
            }
        }
        
        return primaryEmailReturn;
    
    }
}

Test Class
@isTest
public class StudentsService_Test {

    static testMethod void  test_primary_email_with_same_modified_date() {
        
        Students__c student = insertStudents(1);
        insert student;
        
        Students__c studentAfterUpdate = [SELECT Email1__c, Email2__c, Email3__c, Email4__c, Email1Date__c, Email2Date__c, Email3Date__c, Email4Date__c,
                                         	Email1Days__c, Email2Days__c, Email3Days__c, Email4Days__c, PrimaryEmail__c FROM Students__c WHERE Id = :student.Id];
        system.assert(studentAfterUpdate.PrimaryEmail__c == student.Email1__c);
        
    }
    
    static testMethod void  test_primary_email_with_different_modified_date() {

        Students__c student = insertStudents(1);
        insert student;
     
        student.Email1Date__c = student.Email1Date__c.addDays(-4);
        student.Email2Date__c = student.Email2Date__c.addDays(-3);
        student.Email3Date__c = student.Email3Date__c.addDays(-2);
        student.Email4Date__c = student.Email4Date__c.addDays(-1);
        update student;

        Students__c studentAfterUpdate = [SELECT Email1__c, Email2__c, Email3__c, Email4__c, Email1Date__c, Email2Date__c, Email3Date__c, Email4Date__c,
                                         	Email1Days__c, Email2Days__c, Email3Days__c, Email4Days__c, PrimaryEmail__c FROM Students__c WHERE Id = :student.Id];
        system.assert(studentAfterUpdate.PrimaryEmail__c == student.Email4__c);
        
    }
    
    
    private static Students__c insertStudents(Integer counter) {
        
        Students__c student = new Students__c();
        student.Email1__c = 'Email1_' + String.valueOf(counter) + '@test.com';
        student.Email2__c = 'Email2_' + String.valueOf(counter) + '@test.com';
        student.Email3__c = 'Email3_' + String.valueOf(counter) + '@test.com';
        student.Email4__c = 'Email4_' + String.valueOf(counter) + '@test.com';
        
        student.Email1Date__c = Date.today();
        student.Email2Date__c = Date.today();
        student.Email3Date__c = Date.today();
        student.Email4Date__c = Date.today();
        
        return student;
        
    }
}

Let me know your thoughts

All Answers

Gwirizanani SinoiaGwirizanani Sinoia
I meant able to exempt other users from updating not all
 
Suraj GharatSuraj Gharat
In a nutshell, you need your PrimaryEmail to store most recently updated email address among the four email addresses, unless PrimaryEmail is specified by user in the same request explicitly. 

If this is the case, you may use Process Builder, to update PrimaryEmail as required.
Gwirizanani SinoiaGwirizanani Sinoia
Thanks for the answer however process builder wont work. The question is how are you going to find the lowest numbers of days with a process? Which will then determine your Primary email field update. 
Suraj GharatSuraj Gharat
Determining Primary Email is the only reason behind lowest-number-of-days logic ?

If it is, then we can do it without calculating lowest number of days. We can use ISCHNAGED function in Process Builder to determine if any of our four emails is changed, if it does then update Primary Email with that value.

 
Gwirizanani SinoiaGwirizanani Sinoia
@Suraj Gharat
The Primary Email is not the only reason. 
Background
The email addresses get values from external systems through an over night batch. With that in mind a process wont be ideal.
Another issue is sometimes all Email addreses can be updated at the same time  providing us with multiple options.The logic should cater for this type of change by only populating Primary Email Address according to prioirty of the source ie Email1 will take priority over all the other  email addresses. Subsequently Email2 over the remaining addreses except Email1 etc.

 
Suraj GharatSuraj Gharat
Processs and workflows could be triggered even though we create/update data through APIs. I think solutions without code are better and ideal in Salesforce ecosystem. Anyway, if I had to do this by Apex trigger I would do it this way.
 
if(Trigger.isInsert && Trigger.IsBefore){
        for(CustomObject1__c data : Trigger.new){
            if(string.isBlank(data.Primary_Email__c)){
                data.Primary_Email__c = (string.isBlank(data.Email1__c) ? 
                                            (string.isBlank(data.Email2__c)	?
                                                (string.isBlank(data.Email3__c)	?
                                                    (string.isBlank(data.Email4__c)	?
                                                    	data.Primary_Email__c:
                                                    	data.Email4__c):
                                                    data.Email3__c):
                                             	data.Email2__c) :
                                         	data.Email1__c);
            }
        }
    }
    else if(Trigger.isUpdate && Trigger.IsBefore){
        for(integer i = 0;i<Trigger.size;i++){
            if(Trigger.old[i].Primary_Email__c == Trigger.new[i].Primary_Email__c){
                Trigger.new[i].Primary_Email__c = (Trigger.old[i].Email1__c == Trigger.new[i].Email1__c ? 
                                                    (Trigger.old[i].Email2__c == Trigger.new[i].Email2__c	?
                                                        (Trigger.old[i].Email3__c == Trigger.new[i].Email3__c	?
                                                            (Trigger.old[i].Email4__c == Trigger.new[i].Email4__c	?
                                                                Trigger.new[i].Primary_Email__c:
                                                                Trigger.new[i].Email4__c):
                                                            Trigger.new[i].Email3__c):
                                                        Trigger.new[i].Email2__c) :
                                                    Trigger.new[i].Email1__c);
            }
        }
    }

 
Abdul KhatriAbdul Khatri
I hope the following code help you mission accomplished. Please let me know
 
trigger UpdateStudentPrimaryEmail on Students__c (before Insert, before update) {
    
    Map<Id, Students__c> studentMap = new Map<Id, Students__c>();
    List<Students__c> studentList = new List<Student__c>();
    
    for(Students__c student : trigger.new) {
        
        if(trigger.isInsert() || 
           (trigger.isUpdate() && 
            (student.Email1__c != oldMap.get(student.Id).Email1__c ||
           	student.Email2__c != oldMap.get(student.Id).Email2__c ||
           	student.Email3__c != oldMap.get(student.Id).Email3__c ||
           	student.Email4__c != oldMap.get(student.Id).Email4__c))
          )
        {
            studentList.add(student);
            
        }
    }
    
    if(studentList.isEmpty()) return;  
    
    for(Students__c studentRec : studentList){
        
        studentRec = getPrimaryEmail(studentRec);
        
    } 
    
}

public String getPrimaryEmail (Students__c student) {

    Map<String, Integer> emailDaysMap = new Map<String, Integer>();
    String primaryEmailReturn;
    
    if(student.Email1__c != null && student.Email1Days != null)	
        emailDaysFieldMap.put(student.Email1__c, student.Email1Days);
    
    if(student.Email2__c != null && student.Email2Days != null)	
        emailDaysFieldMap.put(student.Email2__c, student.Email2Days);
    
    if(student.Email3__c != null && student.Email3Days != null)	
        emailDaysFieldMap.put(student.Email3__c, student.Email3Days);
    
    if(student.Email4__c != null && student.Email4Days != null)	
        emailDaysFieldMap.put(student.Email4__c, student.Email4Days); 
    
    if(emailDaysFieldMap.isEmpty()) return null;

	Integer minDaysLastModified;    
    for(String emailStr : emailDaysFieldMap.keyset()) {
        
        if(minDaysLastModified == null || emailDaysFieldMap.get(emailStr) < minDaysLastModified) {
            primaryEmailReturn = emailStr;
            minDaysLastModified = emailDaysFieldMap.get(emailStr);
        }
    }
    
    return primaryEmailReturn;

}

 
Gwirizanani SinoiaGwirizanani Sinoia
Hi @Abdul Khatri and Suraj Gharat ,
Please review my code .
I did take onboard what you advised. I am also unsure if I would need to creat a custom sort list instead of using the standard list sort method. Please note I have decided to work with dates only. I am open to correction and critisim please feel free to correct the code.

trigger EmailSorting on test_object__c (before update, before insert) {
    
    
    List<datetime> studentList = new List<datetime>();
    
    for(test_object__c student : trigger.new) {
        
        if( (trigger.isBefore &&
            trigger.isInsert) || 
           (trigger.isBefore &&
           trigger.isUpdate )&&(
            student.Email1 != trigger.oldMap.get(student.Id).Email1 && student.Email1!=Null ||
               student.Email2 != trigger.oldMap.get(student.Id).Email2 && student.Emal2!=Null ||
               student.Email3 != trigger.oldMap.get(student.Id).Email3 && student.Email3 !=Null||
               student.Email4!= trigger.oldMap.get(student.Id).Email4 && student.Email4!=Null))
          
        {
          studentList.add(student.Email1Date);
          studentList.add(student.Email2Date);
          studentList.add(student.Email3Date);
          studentList.add(student.Email4Date);  
            
            
         
            
        system.debug(studentList.size());    
           
            
            // Compare list check if all values are equal
            
            if (student.Email1Date == student.Email2Date&& student.Email1== student.Email2Date&&
                student.Email1Date==student.Email3Date && student.Email1Date==student.Email4Date ){
                 
                 student.PrimaryEmail= student.Email1;   
                }
            
           else if ( studentList != null && !studentList.isEmpty()){
                
                studentList.sort();
               
                system.debug(studentList.size());
                system.debug(studentList.get(3));
               
               //Compare list look for the smallest value
               if(student.Email1Date==studentList.get(3)){
                   student.PrimaryEmail=student.Email1;}
               else if(student.Email2Date==studentList.get(3)){
                       student.PrimayEmail=Email2;}
               else if(student.Email3Date==studentList.get(3)){
                       student.PrimaryEmail=student.Email3;}
               else if(student.Email4Date==studentList.get(3)){
                       student.PrimaryEmail=student.Email4;}               
                
            }
            
            
        }

}
}
Gwirizanani SinoiaGwirizanani Sinoia
Its not updating
Abdul KhatriAbdul Khatri
I am sorry but I do not understand your code. I am totally lost what exactly you wanted to do.
Did you apply my code?
What issue you found with my code?
Gwirizanani SinoiaGwirizanani Sinoia
yes @ Abdul Khatri it had a lot of syntax errors. List dont have the maps dont have the same names and trigger.isUpdate() . Sorry it was not my intensions not to use your code. I am new in at this . Thanks for your help
Abdul KhatriAbdul Khatri
Sorry for the hassle but here is the complete solution with the Test class (coverage = 100%)

Trigger
trigger UpdateStudentPrimaryEmail on Students__c (before Insert, before update) {
    
    for(Students__c studentRec : trigger.new){
        
        studentRec.PrimaryEmail__c =  StudentsService.getPrimaryEmail(studentRec);
        
    }    
}

Class
public class StudentsService {

    public static String getPrimaryEmail (Students__c student) {
    
        Map<String, Date> emailDateMap = new Map<String, Date>();
        String primaryEmailReturn;
        
        if(student.Email1__c != null) 
            emailDateMap.put(student.Email1__c, student.Email1Date__c);
        
        if(student.Email2__c != null && student.Email2Days__c != null) 
            emailDateMap.put(student.Email2__c, student.Email2Date__c);
        
        if(student.Email3__c != null && student.Email3Days__c != null) 
            emailDateMap.put(student.Email3__c, student.Email3Date__c);
        
        if(student.Email4__c != null && student.Email4Days__c != null) 
            emailDateMap.put(student.Email4__c, student.Email4Date__c);
        
        if(emailDateMap.isEmpty()) return null;
    
        Date emailLastModifiedDate;    
        for(string email : emailDateMap.keySet()) {
            if(emailLastModifiedDate == null || emailDateMap.get(email) > emailLastModifiedDate) {
                primaryEmailReturn = email;
                emailLastModifiedDate = emailDateMap.get(email);
            }
        }
        
        return primaryEmailReturn;
    
    }
}

Test Class
@isTest
public class StudentsService_Test {

    static testMethod void  test_primary_email_with_same_modified_date() {
        
        Students__c student = insertStudents(1);
        insert student;
        
        Students__c studentAfterUpdate = [SELECT Email1__c, Email2__c, Email3__c, Email4__c, Email1Date__c, Email2Date__c, Email3Date__c, Email4Date__c,
                                         	Email1Days__c, Email2Days__c, Email3Days__c, Email4Days__c, PrimaryEmail__c FROM Students__c WHERE Id = :student.Id];
        system.assert(studentAfterUpdate.PrimaryEmail__c == student.Email1__c);
        
    }
    
    static testMethod void  test_primary_email_with_different_modified_date() {

        Students__c student = insertStudents(1);
        insert student;
     
        student.Email1Date__c = student.Email1Date__c.addDays(-4);
        student.Email2Date__c = student.Email2Date__c.addDays(-3);
        student.Email3Date__c = student.Email3Date__c.addDays(-2);
        student.Email4Date__c = student.Email4Date__c.addDays(-1);
        update student;

        Students__c studentAfterUpdate = [SELECT Email1__c, Email2__c, Email3__c, Email4__c, Email1Date__c, Email2Date__c, Email3Date__c, Email4Date__c,
                                         	Email1Days__c, Email2Days__c, Email3Days__c, Email4Days__c, PrimaryEmail__c FROM Students__c WHERE Id = :student.Id];
        system.assert(studentAfterUpdate.PrimaryEmail__c == student.Email4__c);
        
    }
    
    
    private static Students__c insertStudents(Integer counter) {
        
        Students__c student = new Students__c();
        student.Email1__c = 'Email1_' + String.valueOf(counter) + '@test.com';
        student.Email2__c = 'Email2_' + String.valueOf(counter) + '@test.com';
        student.Email3__c = 'Email3_' + String.valueOf(counter) + '@test.com';
        student.Email4__c = 'Email4_' + String.valueOf(counter) + '@test.com';
        
        student.Email1Date__c = Date.today();
        student.Email2Date__c = Date.today();
        student.Email3Date__c = Date.today();
        student.Email4Date__c = Date.today();
        
        return student;
        
    }
}

Let me know your thoughts
This was selected as the best answer
Gwirizanani SinoiaGwirizanani Sinoia
Thanks so much Abdul Khatri