Несколько вещей, которые вы можете улучшить здесь, с чего начать ...
Инициализация (?) Кусок
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 Почему "глобальный" повсюду?