0

Facing issue while running the trigger , However unable to find the issue as code is moreover optimised and using map already. Logic is on the basis of field A and B find related record in another object and if present sum the new record with latest number else create a new record.

The time consumption majorly it shows inside update statement , when I run and analysed using log analyser.

trigger Trigger ABAggregate on ABPayout (after insert,after update,after delete) {
    Map<String,Set<String>> resultMapMPAT = new Map<String,Set<String>>();
    Set<String> MPAT = new Set<String>();
    Set<String> MPATMember = new Set<String>();
    
    for(ABPayout processRecord : Trigger.new){
        System.debug('Trigger size : '+Trigger.new.size());
        if(processRecord.Keypat__C!=null ){
            Set<String> MPATAggregate = new Set<String>();
            if(resultMapMPAT.get(processRecord.Keypat__C)!=null){
                MPATAggregate= resultMapMPAT.get(processRecord.Keypat__C);
                MPATAggregate.add(processRecord.MemberId); 
            }else{
                MPATAggregate.add(processRecord.MemberId);  
                resultMapMPAT.put(processRecord.Keypat__C, MPATAggregate); 
            }
        }
    }    
    
    Map<string,parentAggPay__C> mpatmemberagrregate = new Map<string,parentAggPay__C>();
    List<parentAggPay__C> aggregateToCreate = new List<parentAggPay__C>();
    List<parentAggPay__C> aggregateToUpdate = new List<parentAggPay__C>();

    List<parentAggPay__C> aggregateList = [select id,PMMember__c,Keypat__C,VLdiscount__c from parentAggPay__C where Keypat__C in:resultMapMPAT.keyset()];
    if(aggregateList.size()>0){
    for(parentAggPay__C agg : aggregateList){
        String rebateProgramMPATId=String.valueOf(agg.Keypat__C).substring(0, 15);
        String memberId=String.valueOf(agg.PMMember__c).substring(0, 15);
        mpatmemberagrregate.put(rebateProgramMPATId+'-'+memberId,agg);
    }    
    }    
    System.debug('mpatmemberagrregate : '+mpatmemberagrregate);
    
    For(ABPayout mp:trigger.new){
        if(mp.Keypat__C!=null){
            String rebateProgramMPATId=String.valueOf(mp.Keypat__C).substring(0, 15);
            String memberId=String.valueOf(mp.MemberId).substring(0, 15);
            parentAggPay__C aggregate = mpatmemberagrregate.get(rebateProgramMPATId+'-'+memberId);
            if(aggregate!=null){
                Decimal oldAmount = Trigger.oldMap.get(mp.Id).TotalRebateAmount;
                aggregate.VLdiscount__c = (aggregate.VLdiscount__c - oldAmount)+ mp.TotalRebateAmount;
                aggregateToUpdate.add(aggregate);
            }else{
                aggregate = new parentAggPay__C();
                aggregate.PMMember__c = mp.memberId;
                aggregate.Keypat__C = mp.Keypat__C;
                aggregate.VLdiscount__c = mp.totalrebateamount;
                aggregateToCreate.add(aggregate);
            }
        }
    }
    
    System.debug('aggregateToCreate : '+aggregateToCreate);
    System.debug('aggregateToUpdate : '+aggregateToUpdate);
    
    if(aggregateToCreate.size()>0){
        insert aggregateToCreate;
    }if(aggregateToUpdate.size()>0){
        map<id,parentAggPay__C> mapAggUpd = new map<id,parentAggPay__C>();
        mapAggUpd.putall(aggregateToUpdate);
        update mapAggUpd.values();
    }
    System.debug('aggregateToCreate : '+aggregateToCreate);
    System.debug('aggregateToUpdate : '+aggregateToUpdate);
    
}
2
  • is this the only logic running on those objects? No other triggers, workflow, record-trigger flow, etc? Sep 19, 2022 at 11:28
  • No , these are the only objects
    – Marvel
    Sep 19, 2022 at 11:31

1 Answer 1

1

Your code has a lot of logic bugs in it. resultMapMPAT should be a plain old Set, Trigger.new can't be used in an after delete trigger, you should never truncate 18-character ID values like that (it's only by a happy accident that your code works with 15-character ID values here), and the code is overall inefficient. However, none of that actually means to say that this code could possibly cause a CPU limit to occur. I find it unlikely that this trigger can, itself, cause a CPU timeout, unless you have many, many records to deal with. That said, we can heavily optimize this to fix all the problems and likely eliminate the CPU limit exception.

trigger ABAggregate on ABPayout (after insert,after update,after delete,after undelete) {
    Set<String> keypatIds = new Set<String>();
    // Insert and update
    if(Trigger.new != null) {
        for(ABPayout processRecord: Trigger.new) {
            keypatIds.add(processRecord.Keypat__c);
        }
    }
    // Update and delete
    if(Trigger.old != null) {
        for(ABPayout processRecord: Trigger.old) {
            keypatIds.add(processRecord.Keypat__c);
        }
    }
    // Remove null value
    keypatIds.remove(null);

    Map<parentAggPay__C,parentAggPay__C> mpatmemberagrregate = new Map<parentAggPay__C,parentAggPay__C>();
    List<parentAggPay__C> updatedAggregates = new List<parentAggPay__C>();

    // Existing records
    for(parentAggPay__C agg : [select PMMember__c, Keypat__c from parentAggPay__c where Keypat__C in :keypatIds]){
        mpatmemberagrregate.put(new parentAggPay__C(Keypat__C=agg.Keypat__C, PMMember__c=agg.PMMember__c),agg);
    }
    // Newly calculated values
    for(AggregateResult result: [
            SELECT Keypat__c keypat, MemberId memberId, SUM(TotalRebateAmount) totalRebateAmount
            FROM ABPayout
            WHERE Keypat__c = :keypatIds
            GROUP BY Keypat__c, MemberId
        ]) {
        parentAggPay__C key = new parentAggPay__C(Keypat__C=mp.Keypat__C, PMMember__c=mp.MemberId);
        parentAggPay__C aggregate = mpatmemberagrregate.remove(key);
        // Record doesn't exist.
        if(aggregate == null) {
            updatedAggregates.add(new parentAggPay__C(
                    PMMember__c = (Id)result.get('memberId'),
                    Keypat__C = (Id)result.get('keypat'),
                    VLdiscount__c = (Decimal)result.get('totalRebateAmount')
                )
            );
        } else {
            // Update the total value
            aggregate.VLdiscount__c = (Decimal)result.get('totalRebateAmount');
            updatedAggregates.add(aggregate);
        }
    }
    // Place new records next to others for DML to be efficient
    updatedAggregates.sort();
    // Insert or update records
    upsert updatedAggregates parentAggPay__c.Id;
    // Delete records that had no totals.
    delete mpatmemberagrregate.values();
}

Of course, I took some liberties in this code, I can't guarantee everything is correct, but this is the general algorithm for doing this kind of summation.

2
  • Thanks for the suggestion will go over the Also , And try to implement and optimize . Just a question what does mp refers here parentAggPay__C key = new parentAggPay__C(Keypat__C=mp.Keypat__C, PMMember__c=mp.MemberId);
    – Marvel
    Sep 19, 2022 at 15:59
  • @Marvel See this answer where I explain it a bit more. We create a composite key to find the matching record efficiently.
    – sfdcfox
    Sep 19, 2022 at 16:39

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .