Я создал функцию для перемещения лидов от кого-то, кто находится в отпуске, однако, когда у пользователя более 100 лидов, эта ошибка возникает, хотя я не вызываю запросы soql внутри циклов for. Возможно, я что-то упускаю здесь, и я был бы очень признателен за любую помощь в этом.

trigger Moveleads on User (after update) {
for(User user: System.Trigger.New)  
{ 
    if(user.On_Vacation__c == true ){
        if(user.User_to_send_leads_to__c == null){
            user.addError('Must specify someone to take their leads');
            user.On_Vacation__c = false;
        }else{
            Lead[] leadsToMove = [SELECT Id, OwnerId, From_someone_on_Vaction__c, Status FROM lead 
                                                                  WHERE OwnerId = :user.Id];
            string userToTakeLeads = user.User_to_send_leads_to__c;
            for(lead x : leadsToMove){
                if(x.From_someone_on_Vaction__c == false && x.Status == 'Not Attempted'){
                    x.OwnerId = userToTakeLeads;
                    x.From_someone_on_Vaction__c = true;
                    x.User_leads_are_from__c = user.id;
                }
            }
            Database.DMLOptions dlo = new Database.DMLOptions();
            dlo.EmailHeader.triggerAutoResponseEmail = false;
            dlo.EmailHeader.triggerUserEmail = false;
            dlo.EmailHeader.triggerUserEmail = false;
            dlo.EmailHeader.triggerOtherEmail = false;
            dlo.OptAllOrNone = false;
            database.update(leadsToMove,dlo);
        }
    }else{
        Lead[] leadsToMove = [SELECT Id, OwnerId, From_someone_on_Vaction__c, Status FROM lead WHERE 
                                                              User_leads_are_from__c = :user.Id];
        for(lead x : leadsToMove){
            if(x.From_someone_on_Vaction__c == true){
                x.OwnerId = user.Id;
                x.From_someone_on_Vaction__c = false;
                x.User_leads_are_from__c = '';
            }
        }
        Database.DMLOptions dlo = new Database.DMLOptions();
        dlo.EmailHeader.triggerAutoResponseEmail = false;
        dlo.EmailHeader.triggerUserEmail = false;
        dlo.EmailHeader.triggerUserEmail = false;
        dlo.EmailHeader.triggerOtherEmail = false;
        dlo.OptAllOrNone = false;
        database.update(leadsToMove,dlo);
        }
    }
}
0
Sebastian Kessel 29 Июн 2020 в 18:17
3
Я вижу, что ваш SOQL находится внутри цикла for(User user: System.Trigger.New).
 – 
Hengky Djapar
29 Июн 2020 в 18:06

2 ответа

Лучший ответ

Вся логика вашего кода находится внутри следующего цикла:

for(User user: System.Trigger.New)

Вы также выполняете DML (database.update(leadsToMove,dlo);) внутри того же цикла

Поскольку процессы Salesforce запускаются пакетами, содержащими до 200 записей, вы будете сталкиваться с ограничениями регулятора каждый раз, когда будете обновлять более 100 пользователей одновременно.

У вас есть два запроса, которые можно переместить за пределы этого цикла. Я проиллюстрирую потенциальное исправление одним из них:

Map<Id, List<Lead>> leadsPerUser = new Map<Id, List<Lead>>();
for (Lead l : [SELECT Id, OwnerId, From_someone_on_Vaction__c, Status FROM lead WHERE OwnerId in :Trigger.newMap().keySet()]) {
    if (! leadsPerUser.containsKey(l.OwnerId) {
      leadsPerUser.put(l.OwnerId, new List<Lead>());
    }

    List<Lead> leads = leadsPerUser.get(l.OwnerId);
    leads.add(l);
    leadsPerUser.put(l.OwnerId, leads);
}

Затем, как показано ниже, просто получите список на основе владельца, с которым вы работаете, и обработайте его так, как вы это делаете сейчас.

 List<Lead> leadsToMove = leadsPerUser.get(user.Id);
//Note, Don't forget to check for existence, a user may not have leads)

Я бы также сделал следующие изменения:

  1. удалить все части dml внутри цикла
  2. когда лид нужно изменить, добавить его в новый список
  3. выполните DML в этом списке после цикла for.

Быстрый пример

//Avoid updating the same lead twice
Map<Id, Lead> leadsToUpdate = new Map<Id, Lead>();
for (User u .... ) {
<for loop logic>
    for(lead x : leadsToMove){
       <logic of if statement>
       leadsToUpdate.put(x.id, x);
    }
<rest of for loop logic>
update leadsToUpdate;
        
2
Sebastian Kessel 29 Июн 2020 в 18:16
1
Огромное спасибо за помощь
 – 
chillinOutMaxin
10 Июл 2020 в 17:57

У вас есть запрос в цикле, это оператор else:

for(User user: System.Trigger.New)  
{ 
  if(user.On_Vacation__c == true ){
    ...
  }else{
    Lead[] leadsToMove = [SELECT Id, OwnerId, From_someone_on_Vaction__c, Status FROM lead WHERE ...

Вам нужно будет оптимизировать эту часть логики, чтобы этот запрос выполнялся только один раз.

2
sfdcfox 29 Июн 2020 в 18:08
Не могу поверить, что пропустил это. Виноват. Спасибо, что указали на это
 – 
chillinOutMaxin
10 Июл 2020 в 17:55