Я пытаюсь написать триггер, который устанавливает статус обращения в «Закрыто», если в тот же день (сегодня) создано более двух обращений, связанных с одним и тем же контактом. Проблема в том, что я не хочу использовать запросы SOQL в циклах for или вложенных циклах for. Я пытаюсь сделать это через карту со списком в качестве значения, но не могу заставить его работать. Я изучил это решение: Есть ли способ получить размер списка из map>, но это дает мне еще один цикл for, который делает его вложенным циклом for, который я пытаюсь предотвратить. Вот мой код:

public without sharing class CaseStatusClosed {
    public static void triggerInjection(List<Case> caseList) {

        Set<Id> caseContactIdSet = new Set<Id>();
        Map<Id, Contact> contactById = new Map<Id, Contact>();
        //List<Case> caseAddList = new List<Case>();

        Map<Id, List<Case>> caseListByContactId = new Map<Id, List<Case>>();


        for(Case myCase : caseList){
            if(myCase.CreatedDate == Date.Today()){
                caseContactIdSet.add(myCase.ContactId);
                //caseAddList.add(myCase);
                if(!caseListByContactId.containsKey(myCase.ContactId)){
                    caseListByContactId.put(myCase.ContactId, new List<Case>());
                }
                caseListByContactId.get(myCase.ContactId).add(myCase);
            }
        }

        List<Contact> contList = [SELECT Id FROM Contact WHERE Id IN :caseContactIdSet];
        //Contacts related to cases Id of today

        for(Case myCase : caseList){


            if(caseListByContactId.get(myCase.ContactId) != null && caseListByContactId.get(myCase.ContactId).size() > 2){
                myCase.status = 'Closed';
            }
        }
    }
}
0
Derek F 30 Мар 2020 в 16:48

2 ответа

Лучший ответ

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

Код, который у вас есть прямо сейчас, выглядит довольно близко к правильному. Учитывая, что у вас есть Map<Id, List<Case>>, вы, кажется, уже знаете, что можете использовать .get() на карте, чтобы получить сохраненный List<Case>, а затем вызвать .size(), чтобы получить размер из этого списка.

Если у вас есть только один или два идентификатора контакта, которые вы ищете, вы можете обойтись без цикла. В общем, цикл — правильный инструмент для этой работы.

Вместо этого я подозреваю, что проблема с вашим кодом заключается в том, что вы сравниваете Date с DateTime.

CreatedDate (вопреки своему названию) на самом деле является значением типа DateTime. Сравнение DateTime напрямую с Date, как вы делаете, не сработает.

Для иллюстрации попробуйте запустить этот код через анонимный апекс.

DateTime myDT = DateTime.newInstance(2020, 3, 30);
Date myDate = Date.newInstance(2020, 3, 30);

if(myDT == myDate){
    system.debug('Same day');
}else{
    system.debug('Different day');
}

Вы обнаружите, что отладка системы, которую мы получаем, это «Другой день».

Если вы сделаете небольшое изменение, это сработает. DateTime имеет метод .date(), который извлекает только дату из DateTime. Поскольку теперь вы сравниваете два экземпляра Date друг с другом, все будет работать так, как вы ожидаете.

Применительно к вашему собственному коду измените следующую строку

if(myCase.CreatedDate == Date.Today()){

Быть этим вместо

// Note that we are now calling .date() to make sure we're comparing two dates
if(myCase.CreatedDate.date() == Date.Today()){

Несколько советов на прощание

Вообще говоря, когда вы обнаружите, что что-то «не работает», это только первый шаг на пути к исправлению ошибок. Чтобы иметь возможность исправить это или получить помощь в его устранении, вам нужно попытаться выяснить, в каких конкретных частях возникла проблема.

Лично я склоняюсь к следующему подходу

  • Визуально проверьте код, есть ли в нем что-то явно не так? (я что-то неправильно написал, использовал неправильный метод и т.д.)
  • Попытайтесь убедиться, что определенные вещи работают так, как я думаю, они должны
    • Обычно это означает взять небольшую часть кода, например caseListByContactId.get(myCase.ContactId).size() > 2, и написать достаточно апекса (через анонимный апекс), чтобы заполнить map<id, list<sobject>>, чтобы я мог выполнить system.debug()
  • После этого я начну с известной точки отказа (Дела, которые должны закрываться, не закрываются) и буду работать в обратном направлении.
    • Дойдем ли мы до финального оператора if?
    • Мы вообще подходим к этому последнему циклу?
    • Возвращает ли запрос для contList какие-либо строки?
    • и т. д.
  • Просмотрите журналы выполнения и добавьте system.debug() в свой код, чтобы увидеть значения переменных, результаты выражений или вообще достигли ли вы определенной точки в своем коде.

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

2
Derek F 30 Мар 2020 в 16:48

Спасибо за помощь, Дерек, и ты был совершенно прав. Я начинающий разработчик, поэтому всем спасибо за советы. Я сохранил их в документе Word, чтобы всегда иметь их в качестве ссылки. Применяя метод System.debug для отладки моего кода, я наткнулся на ошибку в своем коде. Вместо того, чтобы получать размер из всех случаев в базе данных, я получал размер своего списка конструкторов. Так что с помощью вашей настройки и собственной отладки я понял, что пошло не так, и изменил то, что было нужно. Настоящим мой окончательный код:

public  without sharing class CaseStatusClosed {
public static void triggerInjection(List<Case> caseList) {


    Map<Id, Contact> contactById = new Map<Id, Contact>();
    Map<Id, List<Case>> caseListByContactId = new Map<Id, List<Case>>();

    List<Case> caseQueryList = [SELECT Id, ContactId FROM Case WHERE CreatedDate = TODAY];

    for(Case myCase : caseQueryList){
        if(!caseListByContactId.containsKey(myCase.ContactId)){
            caseListByContactId.put(myCase.ContactId, new List<Case>());
        }
        caseListByContactId.get(myCase.ContactId).add(myCase);
    }


    for(Case myCase : caseList){
        System.debug(caseListByContactId.get(myCase.ContactId).size());
        if(caseListByContactId.get(myCase.ContactId) != null 
        && caseListByContactId.get(myCase.ContactId).size() > 2){

            myCase.status = 'Closed';
        }
    }
}

}

0
wfrankhuizen 30 Мар 2020 в 18:02