В приведенном ниже коде я получаю сообщение Salesforce «Ограничение времени процессора Apex превышает исключение». Пожалуйста, помогите мне оптимизировать код или как решить эту проблему. Любая помощь будет очень признательна.

public static Map<String, Object> getCFAccountOverdue(Set<String> cfAccountIdSet ) {
    Map<String, Object> cfAccountOverdueMap = new Map<String, Object>();
    Map<String, Decimal> overdueDateRangeMap = new Map<String, Decimal>();

    for(Schema.pickListEntry eachVal : CF_Claim__c.Overdue_Date_Ranges__c.getDescribe().getPicklistValues()){
        overdueDateRangeMap.put(eachVal.getValue(), 0);
    }
        for(CF_Claim__c eachClaim : [SELECT CF_Account__c, Overdue_In_Days__c, Amount__c  FROM CF_Claim__c  WHERE CF_Account__c IN:cfAccountIdSet AND Status__c = 'Open' ORDER BY CF_Account__c,Overdue_In_Days__c Nulls last]) {                
            if( !cfAccountOverdueMap.containsKey(eachClaim.CF_Account__c) ) {   
                Map<String, Decimal> dateRangeMap = new Map<String, Decimal>(); 
                dateRangeMap.putAll(overdueDateRangeMap);
                dateRangeMap.put(eachClaim.Overdue_In_Days__c, eachClaim.Amount__c != null ? eachClaim.Amount__c : 0);
                cfAccountOverdueMap.put(eachClaim.CF_Account__c, dateRangeMap);                    
            }else {
                Map<String, Decimal> dateRangeMap = (Map<String, Decimal>)cfAccountOverdueMap.get(eachClaim.CF_Account__c);
                dateRangeMap.put(eachClaim.Overdue_In_Days__c, ((dateRangeMap.get(eachClaim.Overdue_In_Days__c)) + (eachClaim.Amount__c != null ? eachClaim.Amount__c : 0)));
                cfAccountOverdueMap.put(eachClaim.CF_Account__c, dateRangeMap);
            }
        }
    return cfAccountOverdueMap; 
}
0
David Reed 23 Авг 2018 в 15:37
3
Сколько записей вы получаете в запросе?
 – 
Tushar Sharma
23 Авг 2018 в 15:30
Salesforce имеет ограничение времени ожидания для транзакций, основанное на использовании ЦП. …
 – 
codeyinthecloud
23 Авг 2018 в 17:02

1 ответ

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

Пожалуйста, рассмотрите возможность использования GROUP BY с ROLLUP и агрегатная функция SUM. Я думаю, что они дадут вам то, что вам нужно, и могут решить проблему с процессорным временем.

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

public static Map<Id, Map<String, Decimal>> getCFAccountOverdue(Set<String> cfAccountIdSet ) {
    Map<Id, Map<String, Decimal>> cfAccountOverdueMap = new Map<Id, Map<String, Decimal>>();
    Map<String, Decimal> overdueDateRangeMap = new Map<String, Decimal>();

    for(Schema.pickListEntry eachVal : CF_Claim__c.Overdue_Date_Ranges__c.getDescribe().getPicklistValues()){
        overdueDateRangeMap.put(eachVal.getValue(), 0);
    }

    AggregateResult[] aggrs = [
        // sumAmount is an alias for the SUM result
        SELECT SUM(Amount__c) sumAmount,
            CF_Account__c, Overdue_In_Days__c,
            // we need GROUPING to indicate if we need to include this in mapping
            GROUPING(CF_Account__c) grpAcc,
            GROUPING(Overdue_In_Days__c) grpOverdue
        FROM CF_Claim__c
        //HAVING is WHERE for aggregate queries
        HAVING CF_Account__c IN :cfAccountIdSet
        // grouping by 2 fields
        GROUP BY 
            ROLLUP(
                CF_Account__c,
                Overdue_In_Days__c
            )
    ];

    for (AggregateResult res : aggrs) {
        if (res.get('grpAcc') == 1 || res.get('grpOverdue') == 1) {
            // it's a total aggr by only one of the fields
            continue;
        }
        Id accId = res.get('CF_Account__c');
        if(!cfAccountOverdueMap.containsKey(accId)) {   
            cfAccountOverdueMap.put(accId, new Map<String, Decimal>());
            cfAccountOverdueMap.get(accId).putAll(overdueDateRangeMap);
        }
        String overdue = res.get('Overdue_In_Days__c');
        Decimal sumAmount = res.get('sumAmount');
        cfAccountOverdueMap.get(accId).put(overdue, sumAmount);
    }
    return cfAccountOverdueMap;
}
1
nchursin 23 Авг 2018 в 21:47
Привет. Большое спасибо за ваш ответ и отличную оптимизацию кода. Но моя проблема здесь в том, что поле «Overdue_In_Days__c» - это поле формулы, которое не может быть сгруппировано по ошибке, которую я получаю. Если в случае любого другого подстрекательства было бы большим подспорьем :)
 – 
Pulikunta Fazur
24 Авг 2018 в 06:26
Фазур Я думал, как помочь в вашей ситуации, не создавая сумасшедший обходной путь с дублированием результата формулы в какое-то другое поле, или вычисляя его без формулы... И, извините, ничего не пришло в голову :( Вы все еще можете проголосовать за идею разрешить группировку по формулам в success.salesforce :)
 – 
nchursin
24 Авг 2018 в 20:46