Деактивировать пользователя на основании даты последнего входа - PullRequest
0 голосов
/ 05 марта 2020

Сценарий: Деактивировать пользователя, чья дата входа менее 42 с сегодняшнего дня. У меня есть пользователь, чья последняя дата входа в систему 1/22/2020 (формат даты США) / 22/1/2020 5:12 вечера. Здесь я написал пакетный апекс для деактивации. Мой код успешно выполнен, и мой пакетный статус завершен, но запись пользователя не деактивируется.

Вот код:

global class User_Deactivation implements Database.Batchable<SObject>
{
dateTime dt = date.today()-42;
       public String query = 'SELECT Name, LastLoginDate, Id From User WHERE IsActive = true AND LastLoginDate=:dt   ';


    global Database.querylocator start(Database.BatchableContext bc)
    {
       return Database.getQueryLocator(query);
    }

    global void execute(Database.BatchableContext bc,List<User> scope)
    {
        List<User> userList = new List<User>();

        for(User s:scope)
        {
            User u =(user)s;
            userList.add(u);
        }

        if(userList.size() > 0)
        {
            for(User usr : userList)
            {
                usr.isActive = false;
            }
        }
        update userList;
    }

    global void finish(Database.BatchableContext bc)
    {
        AsyncApexJob a = [SELECT Id, Status, NumberOfErrors, JobItemsProcessed, TotalJobItems, CreatedBy.Email
                          FROM AsyncApexJob 
                          WHERE Id = :BC.getJobId()];

        Messaging.SingleEmailMessage mail = new Messaging.SingleEmailMessage();
        String[] toAddresses = new String[] {a.CreatedBy.Email};
        mail.setToAddresses(toAddresses);
        mail.setSubject('Apex Job Status: ' + a.Status);
        mail.setPlainTextBody('The batch Apex job processed ' + a.TotalJobItems + ' batches with '+ a.NumberOfErrors + ' failures.');
        Messaging.sendEmail(new Messaging.SingleEmailMessage[] { mail });
    }
}

, пожалуйста, помогите мне в этом

1 Ответ

0 голосов
/ 06 марта 2020

Несколько вещей, которые вы можете улучшить здесь, с чего начать ...

Инициализация (?) Кусок

dateTime dt = date.today()-42;
String query = 'SELECT Name, LastLoginDate, Id From User WHERE IsActive = true AND LastLoginDate=:dt';

Вам нужно совпадение даты или даты и времени? ? То, как вы это написали, будет соответствовать только тем, кто вошел в систему ровно в полночь. System.debug(dt); сказал бы 2020-01-23T00:00:00.000Z. Это не должен быть знак равенства, он должен быть «меньше» или «меньше или равно».

Или даже лучше - вы можете сделать это немного яснее, что вы хотите сделать, немного больше «семанти *» 1043 * "так что бедняга, который собирается поддерживать это, может понять это без лишних комментариев. Это выглядит более естественным и использует литералы даты SOQL , специальные "константы", чтобы упростить вашу логику c: SELECT Id, LastLoginDate FROM User WHERE isActive = true AND LastLoginDate != LAST_N_DAYS:42

Что такое этот раздел кода в любом случае. Это не совсем переменные c, это не конструктор ... Я думаю, что он будет вести себя как конструктор. Будьте очень, очень осторожны с конструкторами для партий. Состояние класса в конце конструктора сохраняется (сериализуется) и восстанавливается каждый раз, когда запланирован запуск класса. Соблазнительно поместить некоторый код инициализации в конструктор, возможно, прочитать некоторые пользовательские настройки, предварительно рассчитать материал ... Но тогда вы будете удивлены неприятным сюрпризом, когда администратор добавит новые пользовательские настройки, а пакет не заберет их. В вашем случае это еще хуже, я подозреваю, что он сериализует dt, и ваш today() будет заморожен во времени, а не то, что вы ожидали. На всякий случай перенесите все логи инициализации c на start()

И я бы даже сказал, что тот, кто дал вам требование, не продумал его. Когда вы создаете нового пользователя, он получает ссылку, которую нужно щелкнуть в следующие 72 часа. Если они этого не сделали (возможно, оно было отправлено поздно вечером в пятницу, и они хотят войти в систему в понедельник) - эта штука должным образом убьет их доступ в пятницу вечером, не давая им возможности войти в систему. Вам нужен «льготный период». Может быть, что-то вроде WHERE isActive = true AND (LastLoginDate < :x OR (LastLoginDate = null AND CreatedDate < :x))

start ()

Запросы в строках работают, и именно так пишется много пакетной документации, но это плохая практика. По возможности используйте скомпилированный запрос в скобках. Вы получаете минимальное улучшение выполнения (предварительно скомпилированное), вы получаете предупреждения во время компиляции, когда вы ошибаетесь (лучше, чем ошибка времени выполнения, которую вы можете не заметить, если не будете отслеживать задания). И самое главное - если кто-то хочет удалить поле - SF обнаружит зависимость и остановит его / ее. Используйте return Database.getQueryLocator([SELECT ...]); везде, где можете.

execute ()

Ваш scope уже является списком пользователей, почему вы делаете дополнительные приведения к пользователю? Почему вы добавляете их в список помощников? Почему 2 петли?

for(User u : scope){
    u.isActive = false;
}
update users;

и все готово?

PS Почему "глобальный" повсюду?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...