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
Khalid AbdullahKhalid Abdullah 

Apex Trigger help: Update User checkbox field based on UserLogin update

Hello all!

I'm trying to create a trigger that updates a custom "IsFrozen" field when a user's record is frozen.

The User object field, IsFrozen__c is supposed to see if the UserLogin object's IsFrozen field is updated to a value of true, and if so, update the user's record to true. I think this will greatly help us with the userdeactivation process.

My code is as follows:
trigger UserIsFrozen on User (before update) {
    
    for(User U: Trigger.new) {
        User oldU = Trigger.oldMap.get(U.Id);
        
        
        if(oldU.IsActive = true) {
            List<UserLogin> ULog = [SELECT Id, IsFrozen from UserLogin where UserId = :U.Id];
            List<UserLogin> newids = new List<UserLogin>();
            
            for(Userlogin USLog : ULog) {
                if(USLog.IsFrozen = true) {
                    U.IsFrozen__c = true;
                    newids.add(USLog);
                }
            }    
            if(newids.isEmpty()== false) {
                update newids;
                update U;
            }
        }
    }
}

The trigger isn't working right now. What am I doing wrong?
Khalid AbdullahKhalid Abdullah
I updated the code to say:
 
for(Userlogin USLog : ULog) {
                if(USLog.IsFrozen == true) {
                    U.IsFrozen__c = true;
                    newids.add(USLog);

With 2 equal signs for USLog.IsFrozen since it is a comparison.
AzusfdcAzusfdc
Hi Khalid Abdullah Please try for this below code and for your information its parentchild trigger and kindly let me know is it helpful for you then please choose a best answer
 
trigger UserIsFrozen on User (after update) {
    
    Set<Id> sids=new Set<Id>();
    Map<Id,User> mapuser=new Map<Id,User>();
    List<UserLogin> Ullist=new List<UserLogin>();
    
        for(User U: Trigger.new) 
        {
        sids.add(U.id);
        mapuser.put(U.id,U);
        }
    Ullist=[Select id,IsFrozen,UserId from UserLogin where UserId in:sids];
        
       for(UserLogin Ul:Ullist)
       {
       if(mapuser.get(Ul.UserId).IsFrozen__c==true)
       Ul.IsFrozen=mapuser.get(Ul.UserId).IsFrozen__c;
       Ullist.add(Ul);
       }
       
       Update Ullist;
}


 
Ravi Dutt SharmaRavi Dutt Sharma
Azussfdc,

Will this trigger even fire when a user is freezed or unfreezed? Have your tried this in your org? AFAIK, when a user is freezed or unfreezed, the "UserLogin" record is updated. There is no update on the User object. So this trigger will not fire. Thoughts?
Khalid AbdullahKhalid Abdullah
You're absolutely right. How can we make it so that the update to the UserLogin page triggers the update to the User Record?

Would I need to schedule an Apex Class with batchable job that runs on the related user record whenever a record is frozen?

The following updated code only works when we manually "edit" the related User Record:
 
trigger UserIsFrozen on User (before update) {
    
    for(User U: Trigger.new) {

        
        
        if(U.IsActive = true) {
            List<UserLogin> ULog = [SELECT Id, IsFrozen from UserLogin where UserId = :U.Id];
            List<UserLogin> newids = new List<UserLogin>();
            
            for(Userlogin USLog : ULog) {
                if(USLog.IsFrozen == true) {
                    U.IsFrozen__c = true;
                    // newids.add(USLog);
                    }
               }
          }
     }
}

 
Khalid AbdullahKhalid Abdullah
It works when we manually edit the user record and save the record
Ravi Dutt SharmaRavi Dutt Sharma
Yes, your can create a batch job which will be scheduled to run daily. The batch job will fetch the userlogin records which were modified in last 24 hours. Fetch the related user records and update them.
Khalid AbdullahKhalid Abdullah
Hmm... Because of the limited amount we would be using such a batch job, I don't think it's worth it. Would be easier to just select the field on the frozen records ourselves.

I'm just glad the trigger is working as intended. Thanks for your help!
Khalid AbdullahKhalid Abdullah
Azusfdc - Unfortunately, your code is resulting in the following error: 

Error: Invalid Data. 
Review all error messages below to correct your data.
Apex trigger UserIsFrozen caused an unexpected exception, contact your administrator: UserIsFrozen: execution of BeforeUpdate caused by: System.FinalException: Cannot modify a collection while it is being iterated.: Trigger.UserIsFrozen: line 14, column 1

Any thoughts?
Ann rdyAnn rdy
Hi Khalid,

Did you find any solution for this. I have the same issue and wrote a batch class which updates the custome field as Active, Inactive or frozen. Its is working fine but test class is failing for this.

Could someone help with this

Batch Class:

global class UserUpdateBatch implements Database.Batchable<sObject> {

    Public String query;

    global Database.QueryLocator start(Database.BatchableContext BC) {
       //if(!Test.isRunningTest()){
        query = 'SELECT Id, isActive, Status__c FROM User'+(Test.isRunningTest()?' LIMIT 200':'');
      //}  
        return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext BC, List<User> scope) {    
        List<Id> usrLogLst = new List<Id>();
        for(UserLogin ul : [SELECT UserId, isFrozen from UserLogin where isFrozen = true and UserId IN: scope]){
            usrLogLst.add(ul.userid);
        }
        
        for(User usr : scope){
            if(usrLogLst.contains(usr.id)){
                usr.status__c = 'Frozen';
            }
            else{
                if(usr.isActive==true){
                    usr.status__c = 'Active';
                }
                else{
                    usr.status__c = 'Inactive';
                }
            }
        }

        Database.SaveResult [] updateResult = Database.update(scope, false);
        
        for (Database.SaveResult r : updateResult)
        
        {
            if (!r.isSuccess()) 
            {
                for (Database.Error e : r.getErrors())
            { system.debug('Error'+e); }
            
            }
        
        }
               update scope;
    }

    global void finish(Database.BatchableContext BC) {
    }
}

Test Class covering 14% but failed
Error MessageSystem.UnexpectedException: No more than one executeBatch can be called from within a test method. Please make sure the iterable returned from your start method matches the batch size, resulting in one executeBatch invocation.​

@isTest(SeeAllData=false)
private class TestRunAs {
    public static testMethod void testRunAs() {
        
        Profile p = [SELECT Id FROM Profile WHERE Name='System Administrator']; 
        User u = new User(Alias = 'standt', Email='standarduser121we@testorg.com', 
            EmailEncodingKey='UTF-8', LastName='Testing', LanguageLocaleKey='en_US', 
            LocaleSidKey='en_US', ProfileId = p.Id, 
            TimeZoneSidKey='America/Los_Angeles', UserName='standarduse91we233r@testorg.com');
            insert u;
        System.runas(u){
        
            Test.StartTest();
                UserUpdateBatch up =new UserUpdateBatch();
            
           Database.executeBatch(up,13);
           
           test.stoptest(); 
            //   System.abortJob(batchJobId);
    
     }
        }
    }

Test Class Passed but zero code coverage:

@isTest
private class UserUpdateBatch_Test{
Public static TestMethod Void TestActiveUser() {
        Profile p = [Select Id From Profile Where Name='System Administrator'];

        User TestUser = New User( Alias = 'testuser', Email='Moo987@testFrozenUser.com',
         LastName= 'Testme', Firstname= 'you', Languagelocalekey= 'en_US', 
        LocaleSidKey='en_US', Status__c = 'Active', TimeZoneSidkey='America/Los_Angeles', ProfileId=p.id,
         UserName= 'Moo987@testFrozenUser.com', EmailEncodingKey= 'UTF-8');
        insert TestUser;

    test.StartTest();

  ID batchjobid = Database.executeBatch(new UserupdateBatch());
    System.abortJob(batchjobid);

    test.StopTest(); 

        User assertUser= [select Id, Username, Status__c From User Where id=:TestUser.id][0];
     
        System.assertEquals('Active', assertUser.Status__c);
    
    }

Public Static TestMethod Void TestInActiveUser() {

        Profile p = [Select Id From Profile Where Name='System Administrator'];

        User TestUser = New User( Alias = 'Newuser', Email='Moo987@testFrozenUser.com', 
        LastName= 'Testme', Firstname= 'you', Languagelocalekey= 'en_US', 
        EmailEncodingKey= 'UTF-8', Status__c = 'Inactive', LocaleSidKey='en_US', 
        Profileid= P.id, TimeZoneSidkey='America/Los_Angeles',
        UserName= 'Moo987@testFrozenUser.com');
        List<User> lstUsr = new List <User>();                  
        Database.SaveResult userInsertResult= Database.insert(TestUser);
        lstUsr.add(TestUser);
        UserUpdateBatch sh1 = new UserUpdateBatch();
        
        //String sch = '0 0 23 * * ?'; system.schedule('Test', sch, sh1); 
        test.StartTest();
        testUser.IsActive =False;
        Update testuser;
        
   ID batchjobid = Database.executeBatch(new UserupdateBatch());
    System.abortJob(batchJobId);
    
    test.StopTest();

        User assertUser = [Select Id, Username, Status__c From User Where id=:TestUser.id][0];

        System.assertEquals('Inactive', assertUser.Status__c);

 }
}
Einstein TesterEinstein Tester
Hi Ann,
Were you able to get a fix for the above test class that you have written to get code coverage? If yes can you please let me know how were you able to do it and what changes you did in the above test class.
Einstein TesterEinstein Tester
Hi All,
Can anyone please help me in solving the above test class written by Ann. I also have the same scenario where code coverage is showing as 0% but test classes are passing successfully?
SFDC HedgehogSFDC Hedgehog
Hi all,
I know I'm coming late to this party, but the error msg;
"Cannot modify a collection while it is being iterated."

Is caused because it's attempting to change a record that has already been updated  (hence, context "after update").
To do that, you have to re-query the record(s), make your modifications and save.

hth