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
Ananya DhimanAnanya Dhiman 

Trigger on user object to auto populate fields on custom object

Hi Developers, I am new to salesforce, facing problem trying to figure out this question. 

Reuirement - Write trigger on user and create a field on user named - DateOfUser__c of type text. Create a custom object named - New_Object__c with fields as MatchingDates__c (type - date) and a lookup field to user named RelatedUser__c.
Whenever a user is created with a single value in DateOfUser__c field (means date in the format of MM/DD/YY) then a record should be created on custom object with same name as user's name and same date should be auto populated in the custom object's MatchingDates__c field. 
In addition to this if a user is created with multiple values seperated by ';' in DateOfUser__c field then records should be created on custom object based on the number of dates using spilt function. 

For example if I create a user - Ananya with Values in DateOfUser__c as : '01/29/2020;01/30/2020' then 2 records should be created in custom object with same fields as user's fields. 
Fields of user to use here are : Id, Name, DateOfUser__c
Fields of custom object to use here are : Id, Name, MatchingDates__c, RelatedUser__c

Any help will be much appreciated. 
Thanks in advance. :)

Christan G 4Christan G 4
Hi Anaya, as promised, I have updated the code to fulfill the additional requirements. This was actually very fun to work on. I also fixed some errors that I made in my previous solution. If you have any questions regarding the code, please feel free to comment.

Note: I pretended that Account was my custom object that I wanted to insert records to after a user records was created. To customize the code for your scenario, replace "Account" with "New_Object__c" everywhere it is reference

Apex Class Code:
public class UserTriggerHelper {
    
    @future
    public static void autoCreateCustomRecord(List <Id> usrIdList) {
       
    List <User> usrList = [SELECT ID, Name, DateOfUser__c FROM User WHERE ID IN 
    :usrIdList];    
        
    List <Account> newCustomRecList = new List <Account>();
        
        for (User singUsr : usrList) {
            
            //This method executes if only one date is entered without ;
            if (singUsr.DateOfUser__c != null && (!singUsr.DateOfUser__c.containsAny(';'))) {
            
            Date dt = Date.parse(singUsr.DateOfUser__c); 
                
            newCustomRecList.add(new Account(MatchingDates__c = dt,
                                                   Name = singUsr.Name,
                                                   RelatedUser__c = singUsr.id));
            }
            
            //This method invokes if multiple dates are entered with ';' in between each
            else if (singUsr.DateOfUser__c != null && singUsr.DateOfUser__c.containsAny(';')) {
             
            List <String> dtList = singUsr.DateOfUser__c.split(';');
            System.debug(dtList);

                for (Integer i = 0; i < dtList.size(); i++) {

                    Date dt = date.parse(dtList[i]);
                    
                    newCustomRecList.add(new Account(MatchingDates__c = dt,
                                             		    Name = singUsr.Name,
                                             		    RelatedUser__c = singUsr.id));
                    
                }    
            }
                
          }
        
       if (newCustomRecList.size() > 0) {
                
       insert newCustomRecList;
                
} 
}
}

Apex Trigger Code:
trigger UserTrigger on User (after insert) {

    List <Id> triggerIDs = new List <Id>(Trigger.newMap.keyset());
    UserTriggerHelper.autoCreateCustomRecord(triggerIDs);
    
}
Ananya DhimanAnanya Dhiman
Hi @christan, this was very helpful. Thank you so much for your quick response :) Also can you help me with the test class for this same code?! Since I am new to salesforce so dont have much exposure of test classes. Thanks in advance. 
Christan G 4Christan G 4
For sure Ananya. I will try my best to post a test class by the end of the day. Afterwards, you can inquire about any of the code that I have written. Expect a response soon! :)
Christan G 4Christan G 4
Hey Ananya, I hope you are well. Below is the test code to test the code I have written. Even though it tests the code I have written 100%, my system assertion  methods were giving me some weird results. For example, it created 2 accounts for each user twice rather than once. However, when I tested this by creating a user directly in Salesforce, it processed each user once as it should. I am not user if it is how I written the test class that is causing this issue. I plan to investigate this later but the code I have written should work and fully fulfill your requirements. If you have any questions, feel free to comment below.
 
@isTest
public class UserTriggerTest {

    @isTest static void autoCreateCustomRecordTest() {
        
     //Setup   
        
     //Profile ID for Standard User   
     Profile StandardUsr = [SELECT Id from Profile WHERE Name = 'Standard User' LIMIT 1];   
     
     System.debug(StandardUsr.id);   
        
     //Create one Test Account 
     Account acc1 = new Account(Name = 'Test Account #500');
        
     insert acc1;
      
        
     //List to new Users 
     List <User> usrTestList = new List <User>();   
        
        for (Integer i = 0; i < 100; i++) {
            
        //Creates 100 test users with just one date and no ;    
        usrTestList.add(new User(LastName = 'LastName Test'+ i,
                                  Alias = 'Usr'+i,
                                  Email = 'Classtestuser'+ i +'@curious-fox.com',
                                  Username = 'Classtestuser' + i +'@test.com',
                                  CommunityNickname = 'ClassTestUser'+ i,
                                  ProfileId = StandardUsr.Id,
                                  FirstName = 'Test',
                                  DateOfUser__c = '2/03/2020',
                                  TimeZoneSidKey = 'America/Los_Angeles', 
                                  LocaleSidKey = 'en_US',
                                  EmailEncodingKey = 'UTF-8', 
                                  LanguageLocaleKey = 'en_US'));    
            
        }
        
        for (Integer i = 100; i < 200; i++) {
            
        //Creates 100 test users with multiple dates with ";" in between them    
        usrTestList.add(new User(LastName = 'LastName Test' + i,
                                  Alias = 'Usr'+ i,
                                  Email = 'Classtestuser' + i + '@curious-fox.com',
                                  Username = 'Classtestuser'+ i +'@test.com',
                                  CommunityNickname = 'User' + i,
                                  ProfileId = StandardUsr.Id,
                                  FirstName = 'Test',
                                  DateOfUser__c = '2/20/2020;5/20/2020;12/25/2020',
                                  TimeZoneSidKey = 'America/Los_Angeles', 
                                  LocaleSidKey = 'en_US',
                                  EmailEncodingKey = 'UTF-8', 
                                  LanguageLocaleKey = 'en_US')); 
        
         }
        
    System.assertEquals(200, usrTestList.size()); //Verifies that this list now contains 200 users
    
    //Start Test       
    System.Test.startTest();  

    insert usrTestList;
    
    Map<Id, User> usrTestListMap = new Map <Id, User>(usrTestList);
    List <ID> usrTestListIDs = new List <ID>(usrTestListMap.keyset());   
    UserTriggerHelper.autoCreateCustomRecord(usrTestListIDs);    
    
    System.Test.stopTest();
    //End Test 
    
    //Evaluate Test Results    
        
        List <Account> newAcc = [SELECT ID, Name, MatchingDates__c, RelatedUser__c 
                                 FROM Account 
                                 WHERE ID !=:acc1.id];
        
        
        //Verifies that new Accounts were created after the test
        system.assertEquals(true, newAcc.size() > 0);
        
        Date testD1 = date.parse('2/03/2020');
        
        List <Account> firstAccList = [SELECT Name, MatchingDates__c, RelatedUser__c FROM Account WHERE MatchingDates__c =:testD1];
    	
        for (Integer i = 0; i < firstAccList.size(); i++) {
            System.debug(firstAccList[i]);}
        
        System.assertEquals(200, firstAccList.size());
        System.assertEquals(testD1, firstAccList[0].MatchingDates__c);
        
        Date testD2 = date.parse('2/20/2020');
        Date testD3 = date.parse('5/20/2020');
        Date testD4 = date.parse('12/25/2020');
        
        List <Account> secondAccList = [SELECT Name, MatchingDates__c, RelatedUser__c FROM Account WHERE MatchingDates__c =:testD2];
        List <Account> thirdAccList = [SELECT Name, MatchingDates__c, RelatedUser__c FROM Account WHERE MatchingDates__c =:testD3];
        List <Account> fourthAccList = [SELECT Name, MatchingDates__c, RelatedUser__c FROM Account WHERE MatchingDates__c =:testD4];
        
        System.assertEquals(200, secondAccList.size());
       
        
        System.assertEquals(200, thirdAccList.size());
     
        
        System.assertEquals(200, fourthAccList.size()); //Need to evaluate why this returns 200 records and not 300 as thought        
        
        }
    }

 
Ananya DhimanAnanya Dhiman

Hi Christan, you meaningful response was quite helpful. Meanwhile, I wrote an alternative code for this trigger. Can you help me with the test class of this along with assertions. Your help will be much appreciated. 

Thanks a lot. 

Class Code : 
public class AutoPopulate {
    
    @future
    public static void newobjmethod(String jsonString, String jsonOldMap) {
        
        List<User> userlist = (List<User>)JSON.deserialize(jsonString, List<User>.class);
        system.debug('list of New_Object__c after json--'+userlist);
        
        map<id, User> useridmap = (Map<id, User>) JSON.deserialize(jsonOldMap, map<id, User>.class);
        system.debug('map of user after json--'+useridmap);
        
        list<New_Object__c> objlist = new list<New_Object__c>();
        
        for(User u : userlist)
        {
            system.debug('class first loop--'+u);
            if(u.DateOfUser__c != null)
            {
                system.debug('class first if statement--'+u.DateOfUser__c);
                if(useridmap!=null && useridmap.size()>0 && u.DateOfUser__c!=useridmap.get(u.id).DateOfUser__c)
                {
                    if(u.DateOfUser__c.contains(';'))
                    {
                        system.debug('third if--'+u.DateOfUser__c.contains(';'));
                        
                        for(String s : u.DateOfUser__c.split(';'))
                        {
                            system.debug('class for--'+s);
                            New_Object__c n = new New_Object__c();
                            n.RelatedUser__c = u.Id; 
                            n.MatchingDates__c = date.valueof(s); 
                            n.Name = u.LastName;  
                            objlist.add(n);
                            system.debug('new record added to objlist?--'+objlist);
                        }
                    }
                    else{
                        New_Object__c nn = new New_Object__c();
                        nn.RelatedUser__c = u.Id; 
                        nn.MatchingDates__c = date.valueof(u.DateOfUser__c); 
                        nn.Name = u.LastName; 
                        objlist.add(nn);
                    }
                }
            }
        }
        if(objlist!=null && !objlist.isEmpty())
        {
            insert objlist;
            system.debug('inserted records or not?---'+objlist);
        }
    }
}

Trigger Code : 
trigger AutoPopulateFromUser on User (after update) {
    
    if(trigger.isAfter && trigger.isUpdate){
        String jsonString = JSON.serialize(trigger.new);
        String jsonOldMap = JSON.serialize(Trigger.oldMap);
        AutoPopulate.newobjmethod(jsonString,jsonOldMap);
    }
}

Christan G 4Christan G 4
Hi Ananya, and sure! I would be more than happy to help. I have an idea actually but I need to think about it more while writing the test class for it. I should have something by tomorrow the latest.
Christan G 4Christan G 4
Hi Ananyam, I hope you are well. I have a few concerns after reviewing your code more thorougly. Please view my scenario below:

Scenario #1: A list of user names are updated but their values within their date of user field remain the same. Each user within the list has only one value in the date of user field and does not contain ;

Evaluation:
- In this scenario, the line that states if(useridmap!=null && useridmap.size()>0 && u.DateOfUser__c!=useridmap.get(u.id).DateOfUser__c) will return false since value of the date of user field in the new record would be the same as the old record.
- Thus, the rest the code below it will be ignored.

Result: Nothing will happen 

Scenario #2: A list of user names are updated but their values within their date of user field remain the same. Each user within the list has multiples values that are separated by ;

Evaluation:
- In this scenario, the line that states if(useridmap!=null && useridmap.size()>0 && u.DateOfUser__c!=useridmap.get(u.id).DateOfUser__c) will return false since value of the date of user field in the new record would be the same as the old record.

Result: Nothing will happen 

Questions / Concerns: In the above the scenarios, were you expecting for nothing to happen intentionally?

Scenario #3: A list of users' date of field values changed. Each user within the list has multiples values that are separated by ;

Evaluation:
- In this scenario, the line that states if(useridmap!=null && useridmap.size()>0 && u.DateOfUser__c!=useridmap.get(u.id).DateOfUser__c) will return true since value of the date of user field in the new record would not be the same as the old record.
- Thus, the rest the code below it execute.

Result: A new account for each date separated by ; will be created and associated with that user. 

Questions / Concerns: In this scenarios, this will occur each time the date values separted by ; within a user record is updated. Please note that this has the potential to cause duplicates. For example, a user's initial values upon insert for date of user may be 2/30/2020;4/05/2027. After the update, it's new value became 5/20/2020;4/05/2027. Your code executes and two accounts: one with 5/20/2020 and another with 4/05/2027 within its matching field. After the user's record is updated again, it's new value becomes 12/25/2020;4/05/2027. Noticed how only one of its dates have changed. Based on the code you've written, one account will be created with 12/25/2020 as its matching date and a duplicate account with 4/05/2027 will be created. Is this what you were expecting to occur? Just wanted to ensure.

Scenario #4: A list of users' date of field values changed. Each user within the list has only one value in the date of user field and does not contain ;

Evaluation:
- In this scenario, the line that states if(useridmap!=null && useridmap.size()>0 && u.DateOfUser__c!=useridmap.get(u.id).DateOfUser__c) will return true since value of the date of user field in the new record would not be the same as the old record.
- However, when the line executes: if(u.DateOfUser__c.contains(';')) it will return false since it does not contain ;.
- Thus, the rest of the code is ignored.

Result: Nothing will happen. Is this what you were expecting?

Scenario #5: A list of users' name change but don't have a value for date of user.

Evaluation:
- In this scenario, the line that states if(u.DateOfUser__c != null) will return false since there is no value in the date of user field.
- In this situation, the else code block will execute.
- However, when the line executes: nn.MatchingDates__c = date.valueof(u.DateOfUser__c), an error will occur since one can't pass a null value to it.

Result: Nothing will happen or an error will be returned. Is this what you were expecting?
Ananya DhimanAnanya Dhiman
Hi Christan, my requirement was to create records everytime on my custom object only when there is either a single date or multiple dates entered in the DteofUser__c field on user. If the field is null on the user then no records will be created. I understood your point that this will also create duplicate records in case of multiple dates entered but that was the requirement given to me and the code solved the purpose of the task. I have completed the test class for the same. Thank you so much, you have been a great help. :)
Christan G 4Christan G 4
Hi Ananya, I am glad you were able to create a test class for your code. I understood that duplicate records were to be created if multiple dates were entered for the user but I think that should be at the time the user is first inserted rather than each time a user record is updated. As mentioned, this will create a mass amount of duplicate records if user records are updated often so I just wanted to ensure you were aware of that. If this is known and they are okay with this, then awesome! I am happy that I was able to help and I hope you enjoy the rest of your day! 
ALLUMULA VENKATA MANIKANTALLUMULA VENKATA MANIKANT
Hello @Christan G 4 and   @ananya dhiman write a trigger When standard object creates custom should automatically should create And when ever custom object created standard should create automatically but number should be same But number should not be mismatched